diff --git a/src/main/java/com/moing/backend/domain/member/application/service/UpdateRemindAlarmUseCase.java b/src/main/java/com/moing/backend/domain/member/application/service/UpdateRemindAlarmUseCase.java new file mode 100644 index 00000000..0f535603 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/member/application/service/UpdateRemindAlarmUseCase.java @@ -0,0 +1,85 @@ +package com.moing.backend.domain.member.application.service; + +import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; +import com.moing.backend.domain.history.application.service.SaveMultiAlarmHistoryUseCase; +import com.moing.backend.domain.history.domain.entity.AlarmType; +import com.moing.backend.domain.history.domain.entity.PagePath; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.mission.application.service.SendMissionStartAlarmUseCase; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.global.config.fcm.dto.request.MultiRequest; +import com.moing.backend.global.config.fcm.service.MultiMessageSender; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Profile; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +import static com.moing.backend.global.config.fcm.constant.RemindMissionTitle.REMIND_ON_MONDAY_MESSAGE; +import static com.moing.backend.global.config.fcm.constant.RemindMissionTitle.REMIND_ON_MONDAY_TITLE; +@Service +@Transactional +@RequiredArgsConstructor +public class UpdateRemindAlarmUseCase { + + private final MemberGetService memberGetService; + private final SaveMultiAlarmHistoryUseCase saveMultiAlarmHistoryUseCase; + private final MultiMessageSender multiMessageSender; + + String REMIND_NAME = "미션 리마인드"; + + + public Boolean sendUpdateAppPushAlarm() { + + String title = "MOING 업데이트 소식"; + String message = "이제 누구나 미션을 만들 수 있어요. 지금 업데이트하고 다른 소식도 확인해보세요!"; + + List allMemberOfPushAlarm = memberGetService.getAllMemberOfPushAlarm(); + + Optional> memberIdAndTokens = mapToMemberAndToken(allMemberOfPushAlarm); + Optional> pushMemberIdAndToken = isPushMemberIdAndToken(allMemberOfPushAlarm); + + if (pushMemberIdAndToken.isPresent() && !pushMemberIdAndToken.get().isEmpty()) { + multiMessageSender.send(new MultiRequest(pushMemberIdAndToken.get(), title, message, "", REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); + } + if (memberIdAndTokens.isPresent() && !memberIdAndTokens.get().isEmpty()) { + saveMultiAlarmHistoryUseCase.saveAlarmHistories(AlarmHistoryMapper.getMemberIds(memberIdAndTokens.get()), "", title, message, REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue()); + } + return true; + + + } + + public Optional> mapToMemberAndToken(List members) { + return Optional.of(members.stream() + .map(member -> MemberIdAndToken.builder() + .fcmToken(member.getFcmToken()) + .memberId(member.getMemberId()) + .build()) + .collect(Collectors.toList())); + } + public Optional> isPushMemberIdAndToken(List members) { + return Optional.of(members.stream() + .map(member -> { + if (member.isRemindPush() && !member.isSignOut()) { + return MemberIdAndToken.builder() + .fcmToken(member.getFcmToken()) + .memberId(member.getMemberId()) + .build(); + } + return null; + }) + .filter(Objects::nonNull) + .collect(Collectors.toList())); + } + +} diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java index 20217552..fc4474da 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java @@ -3,6 +3,7 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.statistics.application.dto.DailyStats; +import java.util.List; import java.util.Optional; public interface MemberCustomRepository { @@ -12,4 +13,6 @@ public interface MemberCustomRepository { Optional findNotDeletedByEmail(String email); Optional findNotDeletedByMemberId(Long id); DailyStats getDailyStats(); + + Optional> findAllMemberOnPushAlarm(); } diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java index e0d45867..233e6001 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java @@ -8,6 +8,7 @@ import javax.persistence.EntityManager; import java.time.LocalDateTime; import java.time.ZoneId; +import java.util.List; import java.util.Optional; import static com.moing.backend.domain.member.domain.entity.QMember.member; @@ -125,4 +126,18 @@ public DailyStats getDailyStats() { yesterdayOnceMissions); } + @Override + public Optional> findAllMemberOnPushAlarm() { + return Optional.ofNullable( + queryFactory.selectFrom(member) + .where( + member.isDeleted.eq(false), + member.isRemindPush.eq(true), + member.isSignOut.eq(false) + ) + .fetch() + ); + } + + } diff --git a/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java b/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java index 027eb5b4..dbaa3737 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java +++ b/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java @@ -3,12 +3,14 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.repository.MemberRepository; import com.moing.backend.domain.member.exception.NotFoundBySocialIdException; +import com.moing.backend.domain.member.exception.NotFoundRemindAlarmException; import com.moing.backend.domain.statistics.application.dto.DailyStats; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; import javax.transaction.Transactional; import java.math.BigInteger; +import java.util.List; @DomainService @Transactional @@ -27,4 +29,8 @@ public Member getMemberByMemberId(Long memberId) { public DailyStats getDailyStats(){ return memberRepository.getDailyStats(); } + + public List getAllMemberOfPushAlarm() { + return memberRepository.findAllMemberOnPushAlarm().orElseThrow(NotFoundRemindAlarmException::new); + } } diff --git a/src/main/java/com/moing/backend/domain/member/exception/NotFoundRemindAlarmException.java b/src/main/java/com/moing/backend/domain/member/exception/NotFoundRemindAlarmException.java new file mode 100644 index 00000000..679e8d2f --- /dev/null +++ b/src/main/java/com/moing/backend/domain/member/exception/NotFoundRemindAlarmException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.member.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NotFoundRemindAlarmException extends MemberException { + public NotFoundRemindAlarmException() { + super(ErrorCode.NOT_FOUND_ALL_MEMBER, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index 23e1fcf8..82c34bf2 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.missionState.application.service; +import com.moing.backend.domain.member.application.service.UpdateRemindAlarmUseCase; import com.moing.backend.domain.mission.application.service.MissionRemindAlarmUseCase; import com.moing.backend.domain.mission.application.service.SendMissionStartAlarmUseCase; import com.moing.backend.domain.mission.domain.entity.Mission; @@ -31,14 +32,12 @@ public class MissionStateScheduleUseCase { private final MissionStateUseCase missionStateUseCase; private final MissionRemindAlarmUseCase missionRemindAlarmUseCase; private final MissionQueryService missionQueryService; - private final MissionStateQueryService missionStateQueryService; - private final MissionStateDeleteService missionStateDeleteService; + private final UpdateRemindAlarmUseCase updateRemindAlarmUseCase; private final TeamScoreUpdateUseCase teamScoreUpdateUseCase; private final SendMissionStartAlarmUseCase sendMissionStartAlarmUseCase; - /** * 단일 미션 마감 * 해당 시간 미션 마감 @@ -61,4 +60,10 @@ public void MissionRemindAlarm() { missionRemindAlarmUseCase.sendRemindMissionAlarm(); } + + @Scheduled(cron = "0 0 17 * * *") + public void UpdatePushAlarm() { + updateRemindAlarmUseCase.sendUpdateAppPushAlarm(); + } + } diff --git a/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java b/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java index 7abd7a5d..95ee96f4 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java +++ b/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java @@ -9,7 +9,7 @@ public enum RemindMissionTitle { REMIND_MISSION_TITLE1("오늘도 좋은 하루 보내세요!"), REMIND_MISSION_TITLE2("혹시 ... 잊으신 건 아니죠?\uD83D\uDC40"), - REMIND_MISSION_TITLE3("좋은 아침이에요! ☀\uFE0F"), + REMIND_MISSION_TITLE3("아직 인증하지 않은 미션이 있어요!"), REMIND_MISSION_TITLE4("오늘의 열정이 타오르불\uD83D\uDD25"), diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index 4478309a..fc28ead7 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -24,6 +24,7 @@ public enum ErrorCode { TOKEN_INVALID_ERROR("AU0002", "입력 토큰이 유효하지 않습니다."), APPID_INVALID_ERROR("AU0003", "appId가 유효하지 않습니다"), NICKNAME_DUPLICATION_ERROR("AU0004", "닉네임이 중복됩니다."), + NOT_FOUND_ALL_MEMBER("AU0005","푸시 알림을 위한 모든 멤버를 불러오는데 실패했습니다."), //미션 관련 에러코드 NO_ACCESS_CREATE_MISSION("M0001", "소모임장만 미션을 생성할 수 있습니다."), diff --git a/src/test/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryTest.java b/src/test/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryTest.java new file mode 100644 index 00000000..ea725f82 --- /dev/null +++ b/src/test/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryTest.java @@ -0,0 +1,35 @@ +//package com.moing.backend.domain.member.domain.repository; +// +//import com.moing.backend.domain.member.domain.entity.Member; +//import org.junit.jupiter.api.Test; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +//import org.springframework.boot.test.context.SpringBootTest; +//import org.springframework.test.context.ActiveProfiles; +//import org.springframework.transaction.annotation.Transactional; +// +//import javax.persistence.EntityManager; +// +//import java.util.List; +// +//import static org.junit.jupiter.api.Assertions.*; +//@SpringBootTest +//@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +//@ActiveProfiles("dev") +//@Transactional +//class MemberCustomRepositoryTest { +// +// @Autowired +// EntityManager em; +// +// @Autowired +// private MemberRepository memberRepository; +// @Test +// void findAllMemberOnPushAlarm() { +// List members = memberRepository.findAllMemberOnPushAlarm().orElseThrow(); +// for (Member member : members) { +// System.out.println(member.getNickName()); +// } +// +// } +//} \ No newline at end of file