Skip to content

Commit

Permalink
Feature: push notification service (#132)
Browse files Browse the repository at this point in the history
  • Loading branch information
mushroom1324 authored Aug 11, 2024
1 parent 582193e commit a57597a
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,11 @@ public class BagCollect extends ClothingSales{
private Address initAddress;
@Column(name = "bag_quantity")
private Integer bagQuantity;

@Column(name = "notify_count")
private int notifyCount = 0;

public void updateNotifyCount(int notifyCount) {
this.notifyCount = notifyCount;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
import com.example.repick.domain.clothingSales.entity.BagCollect;
import org.springframework.data.jpa.repository.JpaRepository;

public interface BagCollectRepository extends JpaRepository<BagCollect, Long> {
public interface BagCollectRepository extends JpaRepository<BagCollect, Long>, BagCollectRepositoryCustom {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.example.repick.domain.clothingSales.repository;

import com.example.repick.domain.clothingSales.entity.BagCollect;

import java.util.List;

public interface BagCollectRepositoryCustom {
List<BagCollect> findNotProcessedBagCollects();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.example.repick.domain.clothingSales.repository;

import com.example.repick.domain.clothingSales.entity.BagCollect;
import com.example.repick.domain.clothingSales.entity.ClothingSalesStateType;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;

import java.time.LocalDateTime;
import java.util.List;

import static com.example.repick.domain.clothingSales.entity.QBagCollect.bagCollect;

@RequiredArgsConstructor
public class BagCollectRepositoryImpl implements BagCollectRepositoryCustom {

private final JPAQueryFactory jpaQueryFactory;

@Override
public List<BagCollect> findNotProcessedBagCollects() {
return jpaQueryFactory.selectFrom(bagCollect)
.where(
bagCollect.clothingSalesState.in(ClothingSalesStateType.BEFORE_COLLECTION)
.and(bagCollect.createdDate.before(LocalDateTime.now().minusDays(7)))
)
.fetch();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.example.repick.domain.clothingSales.scheduler;

import com.example.repick.domain.clothingSales.entity.BagCollect;
import com.example.repick.domain.clothingSales.repository.BagCollectRepository;
import com.example.repick.global.aws.PushNotificationService;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;

@Component @RequiredArgsConstructor
public class ClothingSalesScheduler {

private final BagCollectRepository bagCollectRepository;
private final PushNotificationService pushNotificationService;

@Scheduled(cron = "0 0 5 * * *", zone = "Asia/Seoul")
public void checkNotProcessedBagInit() {
List<BagCollect> bagCollects = bagCollectRepository.findNotProcessedBagCollects();

bagCollects.forEach(bagCollect -> {
int currentNotifyCount = bagCollect.getNotifyCount() + 1;

if (currentNotifyCount == 1) {
pushNotificationService.sendPushNotification(bagCollect.getUser().getId(), "리픽백 수거를 진행해 보세요!", "지금 바로 진행해 볼까요?");
} else if (currentNotifyCount == 7) {
currentNotifyCount = 0;
}

bagCollect.updateNotifyCount(currentNotifyCount);

});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.example.repick.global.aws;

import com.example.repick.domain.fcmtoken.entity.UserFcmTokenInfo;
import com.example.repick.dynamodb.UserFcmTokenInfoRepository;
import com.example.repick.global.error.exception.CustomException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.lambda.LambdaClient;
import software.amazon.awssdk.services.lambda.model.InvokeRequest;

import static com.example.repick.global.error.exception.ErrorCode.USER_NOT_FOUND;

@Service @RequiredArgsConstructor
public class PushNotificationService {

private final UserFcmTokenInfoRepository userFcmTokenInfoRepository;

public void sendPushNotification(Long userId, String title, String body) {

LambdaClient awsLambda = LambdaClient.builder()
.region(Region.AP_NORTHEAST_2)
.build();

UserFcmTokenInfo userFcmTokenInfo = userFcmTokenInfoRepository.findById(userId)
.orElseThrow(() -> new CustomException(USER_NOT_FOUND));

String json = String.format("{\"fcmToken\": \"%s\", \"title\": \"%s\", \"body\": \"%s\"}", userFcmTokenInfo.getFcmToken(), title, body);

SdkBytes payload = SdkBytes.fromUtf8String(json);

InvokeRequest request = InvokeRequest.builder()
.functionName("lambda_push_notification_single")
.payload(payload)
.build();

awsLambda.invoke(request);

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.example.repick.pushnotification;

import com.example.repick.domain.clothingSales.entity.BagCollect;
import com.example.repick.domain.clothingSales.repository.BagCollectRepository;
import com.example.repick.domain.fcmtoken.entity.UserFcmTokenInfo;
import com.example.repick.dynamodb.UserFcmTokenInfoRepository;
import com.example.repick.global.aws.PushNotificationService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.lambda.LambdaClient;
import software.amazon.awssdk.services.lambda.model.InvokeRequest;
import software.amazon.awssdk.services.lambda.model.InvokeResponse;

import java.util.List;

@SpringBootTest
public class PushNotificationServiceTest {

@Autowired
private UserFcmTokenInfoRepository userFcmTokenInfoRepository;

@Autowired
private BagCollectRepository bagCollectRepository;

@Autowired
private PushNotificationService pushNotificationService;

@Test
public void notificationTest() {
LambdaClient awsLambda = LambdaClient.builder()
.region(Region.AP_NORTHEAST_2)
.build();

String fcmToken = userFcmTokenInfoRepository.findById(3L)
.map(UserFcmTokenInfo::getFcmToken)
.orElseThrow();

String json = String.format("{\"fcmToken\": \"%s\", \"title\": \"test\", \"body\": \"test\"}", fcmToken);

SdkBytes payload = SdkBytes.fromUtf8String(json);

InvokeRequest request = InvokeRequest.builder()
.functionName("lambda_push_notification_single")
.payload(payload)
.build();

InvokeResponse res = awsLambda.invoke(request);

}

@Test
public void pushNotificationServiceCronTest() {
List<BagCollect> bagCollects = bagCollectRepository.findNotProcessedBagCollects();

bagCollects.forEach(bagCollect -> {
int currentNotifyCount = bagCollect.getNotifyCount() + 1;

if (currentNotifyCount == 1) {
pushNotificationService.sendPushNotification(bagCollect.getUser().getId(), "리픽백 수거를 진행해 보세요!", "지금 바로 진행해 볼까요?");
} else if (currentNotifyCount == 7) {
currentNotifyCount = 0;
}

bagCollect.updateNotifyCount(currentNotifyCount);

bagCollectRepository.save(bagCollect);

});

}

}

0 comments on commit a57597a

Please sign in to comment.