Skip to content

Commit

Permalink
[BE] feat: 내 산책 상태 변경 시 나에게 알림 기능 구현 (woowacourse-teams#521)
Browse files Browse the repository at this point in the history
  • Loading branch information
ehtjsv2 authored Aug 22, 2024
1 parent 85096b2 commit d121907
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 36 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.happy.friendogly.footprint.service;

import static com.happy.friendogly.footprint.domain.WalkStatus.AFTER;
import static com.happy.friendogly.footprint.domain.WalkStatus.ONGOING;

import com.happy.friendogly.exception.FriendoglyException;
import com.happy.friendogly.footprint.domain.Footprint;
import com.happy.friendogly.footprint.domain.Location;
Expand All @@ -12,14 +15,11 @@
import com.happy.friendogly.footprint.repository.FootprintRepository;
import com.happy.friendogly.member.domain.Member;
import com.happy.friendogly.member.repository.MemberRepository;
import com.happy.friendogly.notification.domain.DeviceToken;
import com.happy.friendogly.notification.repository.DeviceTokenRepository;
import com.happy.friendogly.notification.service.NotificationService;
import com.happy.friendogly.notification.service.FootprintNotificationService;
import com.happy.friendogly.pet.domain.Pet;
import com.happy.friendogly.pet.repository.PetRepository;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -33,21 +33,18 @@ public class FootprintCommandService {
private final FootprintRepository footprintRepository;
private final MemberRepository memberRepository;
private final PetRepository petRepository;
private final NotificationService notificationService;
private final DeviceTokenRepository deviceTokenRepository;
private final FootprintNotificationService footprintNotificationService;

public FootprintCommandService(
FootprintRepository footprintRepository,
MemberRepository memberRepository,
PetRepository petRepository,
NotificationService notificationService,
DeviceTokenRepository deviceTokenRepository
FootprintNotificationService footprintNotificationService
) {
this.footprintRepository = footprintRepository;
this.memberRepository = memberRepository;
this.petRepository = petRepository;
this.notificationService = notificationService;
this.deviceTokenRepository = deviceTokenRepository;
this.footprintNotificationService = footprintNotificationService;
}

public SaveFootprintResponse save(Long memberId, SaveFootprintRequest request) {
Expand All @@ -67,9 +64,9 @@ public SaveFootprintResponse save(Long memberId, SaveFootprintRequest request) {
.build()
);

List<String> nearDeviceTokens = findNearDeviceTokensWithoutMine(footprint, member);
List<Footprint> nearFootprints = findNearFootprintsWithoutMine(footprint, member);
String comingMemberName = member.getName().getValue();
sendWalkComingNotification(comingMemberName, nearDeviceTokens);
footprintNotificationService.sendWalkComingNotification(comingMemberName, nearFootprints);

return new SaveFootprintResponse(
footprint.getId(),
Expand Down Expand Up @@ -97,14 +94,6 @@ private void validateRecentFootprintExists(Long memberId) {
}
}

private void sendWalkComingNotification(String memberName, List<String> nearDeviceTokens) {
notificationService.sendFootprintNotification(
"반갑개",
"내 산책 장소에 " + memberName + "님도 산책온대요!",
nearDeviceTokens
);
}

public UpdateWalkStatusAutoResponse updateWalkStatusAuto(Long memberId, UpdateWalkStatusAutoRequest request) {
Footprint footprint = footprintRepository.getTopOneByMemberIdOrderByCreatedAtDesc(memberId);
if (footprint.isDeleted()) {
Expand All @@ -115,22 +104,25 @@ public UpdateWalkStatusAutoResponse updateWalkStatusAuto(Long memberId, UpdateWa

footprint.updateWalkStatusWithCurrentLocation(new Location(request.latitude(), request.longitude()));

Member walkStartMember = memberRepository.getById(memberId);
if (beforeWalkStatus.isBefore() && footprint.getWalkStatus().isOngoing()) {
Member startWalkMember = memberRepository.getById(memberId);
List<String> nearDeviceTokens = findNearDeviceTokensWithoutMine(footprint, startWalkMember);
String memberName = footprint.getMember().getName().getValue();
sendWalkStartNotification(memberName, nearDeviceTokens);
List<Footprint> nearFootprints = findNearFootprintsWithoutMine(footprint, walkStartMember);
String memberName = walkStartMember.getName().getValue();
footprintNotificationService.sendWalkStartNotificationToNear(memberName, nearFootprints);
footprintNotificationService.sendWalkNotificationToMe(
memberId,
ONGOING
);
}

return new UpdateWalkStatusAutoResponse(footprint.getWalkStatus(), footprint.findChangedWalkStatusTime());
}
if (beforeWalkStatus.isOngoing() && footprint.getWalkStatus().isAfter()) {
footprintNotificationService.sendWalkNotificationToMe(
memberId,
AFTER
);
}

private void sendWalkStartNotification(String startMemberName, List<String> nearDeviceTokens) {
notificationService.sendFootprintNotification(
"반갑개",
"내 산책장소에 " + startMemberName + "님이 산책을 시작했어요!",
nearDeviceTokens
);
return new UpdateWalkStatusAutoResponse(footprint.getWalkStatus(), footprint.findChangedWalkStatusTime());
}

public UpdateWalkStatusManualResponse updateWalkStatusManual(Long memberId) {
Expand All @@ -147,17 +139,14 @@ public void delete(Long memberId, Long footprintId) {
footprint.updateToDeleted();
}

private List<String> findNearDeviceTokensWithoutMine(Footprint standardFootprint, Member member) {
private List<Footprint> findNearFootprintsWithoutMine(Footprint standardFootprint, Member member) {
LocalDateTime startTime = LocalDateTime.now().minusHours(FOOTPRINT_DURATION_HOURS);
List<Footprint> footprints = footprintRepository.findAllByIsDeletedFalseAndCreatedAtAfter(startTime);

return footprints.stream()
.filter(otherFootprint -> otherFootprint.isInsideBoundary(standardFootprint.getLocation())
&& otherFootprint.getMember() != member
&& !otherFootprint.getWalkStatus().isAfter())
.map(otherFootprint -> deviceTokenRepository.findByMemberId(otherFootprint.getMember().getId()))
.flatMap(Optional::stream)
.map(DeviceToken::getDeviceToken)
.toList();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.happy.friendogly.notification.repository;

import com.happy.friendogly.exception.FriendoglyException;
import com.happy.friendogly.notification.domain.DeviceToken;
import java.util.List;
import java.util.Optional;
Expand All @@ -11,6 +12,10 @@ public interface DeviceTokenRepository extends JpaRepository<DeviceToken, Long>

Optional<DeviceToken> findByMemberId(Long memberId);

default DeviceToken getByMemberId(Long memberId) {
return findByMemberId(memberId).orElseThrow(() -> new FriendoglyException("해당 멤버의 디바이스 토큰을 찾지 못했습니다."));
}

@Query("""
SELECT dt.deviceToken
FROM DeviceToken dt
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.happy.friendogly.notification.service;

import com.happy.friendogly.footprint.domain.Footprint;
import com.happy.friendogly.footprint.domain.WalkStatus;
import com.happy.friendogly.notification.domain.DeviceToken;
import com.happy.friendogly.notification.repository.DeviceTokenRepository;
import java.util.List;
import java.util.Optional;
import org.springframework.stereotype.Service;

@Service
public class FootprintNotificationService {

private final String DEFAULT_TITLE = "반갑개";
private final NotificationService notificationService;
private final DeviceTokenRepository deviceTokenRepository;

public FootprintNotificationService(
NotificationService notificationService,
DeviceTokenRepository deviceTokenRepository
) {
this.notificationService = notificationService;
this.deviceTokenRepository = deviceTokenRepository;
}

public void sendWalkNotificationToMe(Long memberId, WalkStatus currentWalkStatus) {
String content = null;
if (currentWalkStatus.isOngoing()) {
content = "산책을 시작했습니다!";
}
if (currentWalkStatus.isAfter()) {
content = "산책을 종료했습니다!";
}
if (currentWalkStatus.isBefore()) {
return;
}

notificationService.sendFootprintNotification(
DEFAULT_TITLE,
content,
deviceTokenRepository.getByMemberId(memberId).getDeviceToken()
);
}

public void sendWalkComingNotification(String comingMemberName, List<Footprint> nearFootprints) {
List<String> nearDeviceTokens = toDeviceToken(nearFootprints);

notificationService.sendFootprintNotification(
DEFAULT_TITLE,
"내 산책 장소에 " + comingMemberName + "님도 산책온대요!",
nearDeviceTokens
);
}

public void sendWalkStartNotificationToNear(String startMemberName, List<Footprint> nearFootprints) {
List<String> nearDeviceTokens = toDeviceToken(nearFootprints);

notificationService.sendFootprintNotification(DEFAULT_TITLE,
"내 산책장소에 " + startMemberName + "님이 산책을 시작했어요!",
nearDeviceTokens
);
}

private List<String> toDeviceToken(List<Footprint> footprints) {
return footprints.stream()
.map(otherFootprint -> deviceTokenRepository.findByMemberId(otherFootprint.getMember().getId()))
.flatMap(Optional::stream)
.map(DeviceToken::getDeviceToken)
.toList();
}
}

0 comments on commit d121907

Please sign in to comment.