Skip to content

Commit

Permalink
[NAYB-158] feat: 사용자는 배달 상태가 변경되면 알림을 받아볼 수 있다.
Browse files Browse the repository at this point in the history
[NAYB-158] feat: 사용자는 배달 상태가 변경되면 알림을 받아볼 수 있다.
  • Loading branch information
hseong3243 authored Sep 21, 2023
2 parents 4dfdf9b + 214e770 commit 3c2e596
Show file tree
Hide file tree
Showing 10 changed files with 205 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ public class Delivery extends BaseTimeEntity {
@Column
private Integer deliveryFee;

@Column
private Long userId;

@Builder
public Delivery(final Order order, final int estimateMinutes) {
validateOrderStatus(order);
Expand All @@ -80,6 +83,7 @@ public Delivery(final Order order, final int estimateMinutes) {
this.riderRequest = order.getRiderRequest();
this.deliveryFee = order.getDeliveryFee();
this.arrivedAt = LocalDateTime.now().plusMinutes(estimateMinutes);
this.userId = order.getUser().getUserId();
order.updateOrderStatus(OrderStatus.DELIVERING);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.prgrms.nabmart.domain.delivery.service;

import static com.prgrms.nabmart.domain.notification.NotificationMessage.COMPLETE_DELIVERY;
import static com.prgrms.nabmart.domain.notification.NotificationMessage.REGISTER_DELIVERY;
import static com.prgrms.nabmart.domain.notification.NotificationMessage.START_DELIVERY;

import com.prgrms.nabmart.domain.delivery.Delivery;
import com.prgrms.nabmart.domain.delivery.Rider;
import com.prgrms.nabmart.domain.delivery.exception.AlreadyRegisteredDeliveryException;
Expand All @@ -18,6 +22,9 @@
import com.prgrms.nabmart.domain.delivery.service.response.FindDeliveryDetailResponse;
import com.prgrms.nabmart.domain.delivery.service.response.FindRiderDeliveriesResponse;
import com.prgrms.nabmart.domain.delivery.service.response.FindWaitingDeliveriesResponse;
import com.prgrms.nabmart.domain.notification.NotificationType;
import com.prgrms.nabmart.domain.notification.service.NotificationService;
import com.prgrms.nabmart.domain.notification.service.request.SendNotificationCommand;
import com.prgrms.nabmart.domain.order.Order;
import com.prgrms.nabmart.domain.order.exception.NotFoundOrderException;
import com.prgrms.nabmart.domain.order.repository.OrderRepository;
Expand All @@ -37,6 +44,7 @@ public class DeliveryService {
private final UserRepository userRepository;
private final RiderRepository riderRepository;
private final OrderRepository orderRepository;
private final NotificationService notificationService;

@Transactional
public Long registerDelivery(RegisterDeliveryCommand registerDeliveryCommand) {
Expand All @@ -45,12 +53,29 @@ public Long registerDelivery(RegisterDeliveryCommand registerDeliveryCommand) {
checkAlreadyRegisteredDelivery(order);
Delivery delivery = new Delivery(order, registerDeliveryCommand.estimateMinutes());
deliveryRepository.save(delivery);

sendRegisterDeliveryNotification(registerDeliveryCommand, delivery, order);

return delivery.getDeliveryId();
}

private void sendRegisterDeliveryNotification(
RegisterDeliveryCommand registerDeliveryCommand,
Delivery delivery,
Order order) {
SendNotificationCommand notificationCommand = SendNotificationCommand.of(
delivery.getUserId(),
REGISTER_DELIVERY.getTitle(),
REGISTER_DELIVERY.getContentFromFormat(
order.getName(),
registerDeliveryCommand.estimateMinutes()),
NotificationType.DELIVERY);
notificationService.sendNotification(notificationCommand);
}

private void checkUserHasRegisterDeliveryAuthority(final Long userId) {
User user = findUserByUserId(userId);
if(!user.isEmployee()) {
if (!user.isEmployee()) {
throw new UnauthorizedDeliveryException("권한이 없습니다.");
}
}
Expand All @@ -61,7 +86,7 @@ private Order findOrderByOrderIdPessimistic(RegisterDeliveryCommand registerDeli
}

private void checkAlreadyRegisteredDelivery(final Order order) {
if(deliveryRepository.existsByOrder(order)) {
if (deliveryRepository.existsByOrder(order)) {
throw new AlreadyRegisteredDeliveryException("이미 배달이 생성된 주문입니다.");
}
}
Expand Down Expand Up @@ -99,6 +124,19 @@ public void startDelivery(StartDeliveryCommand startDeliveryCommand) {
Delivery delivery = findDeliveryByDeliveryId(startDeliveryCommand.deliveryId());
delivery.checkAuthority(rider);
delivery.startDelivery(startDeliveryCommand.deliveryEstimateMinutes());

sendStartDeliveryNotification(startDeliveryCommand, delivery);
}

private void sendStartDeliveryNotification(
StartDeliveryCommand startDeliveryCommand,
Delivery delivery) {
SendNotificationCommand notificationCommand = SendNotificationCommand.of(
delivery.getUserId(),
START_DELIVERY.getTitle(),
START_DELIVERY.getContentFromFormat(startDeliveryCommand.deliveryEstimateMinutes()),
NotificationType.DELIVERY);
notificationService.sendNotification(notificationCommand);
}

@Transactional
Expand All @@ -107,6 +145,17 @@ public void completeDelivery(CompleteDeliveryCommand completeDeliveryCommand) {
Delivery delivery = findDeliveryByDeliveryId(completeDeliveryCommand.deliveryId());
delivery.checkAuthority(rider);
delivery.completeDelivery();

sendCompleteDeliveryNotification(delivery);
}

private void sendCompleteDeliveryNotification(Delivery delivery) {
SendNotificationCommand notificationCommand = SendNotificationCommand.of(
delivery.getUserId(),
COMPLETE_DELIVERY.getTitle(),
COMPLETE_DELIVERY.getContentFromFormat(),
NotificationType.DELIVERY);
notificationService.sendNotification(notificationCommand);
}

private Rider findRiderByRiderId(final Long riderId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,46 @@

import com.prgrms.nabmart.domain.notification.exception.InvalidNotificationException;
import com.prgrms.nabmart.global.BaseTimeEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import java.util.Objects;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Notification extends BaseTimeEntity {

private static final int CONTENT_LENGTH = 50;
private static final int TITLE_LENGTH = 30;
private static final int CONTENT_LENGTH = 100;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long notificationId;

@Column(nullable = false)
private String title;
private String content;

@Enumerated(EnumType.STRING)
private NotificationType notificationType;

@Column(nullable = false)
private Long userId;

@Builder
public Notification(
String title,
String content,
Long userId,
NotificationType notificationType) {
validateTitle(title);
validateContent(content);
this.title = title;
this.content = content;
this.notificationType = notificationType;
this.userId = userId;
}

private void validateTitle(String title) {
if (Objects.nonNull(title) && title.length() > TITLE_LENGTH) {
throw new InvalidNotificationException("제목의 길이는 20자 이하여야 합니다.");
}
}

private void validateContent(String content) {
if(Objects.nonNull(content) && content.length() > CONTENT_LENGTH) {
if (Objects.nonNull(content) && content.length() > CONTENT_LENGTH) {
throw new InvalidNotificationException("내용의 길이는 50자 이하여야 합니다.");
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.prgrms.nabmart.domain.notification;

import java.text.MessageFormat;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum NotificationMessage {
REGISTER_DELIVERY("주문이 접수되었습니다.",
"주문하신 {0} 이(가) {1}분 내에 도착할 예정입니다."),
START_DELIVERY("라이더가 주문을 픽업하였습니다.", "약 {0}분 후에 도착할 예정입니다."),
COMPLETE_DELIVERY("배달이 완료되었습니다.", "네이B마트를 이용해주셔서 감사합니다.");

private final String title;
private final String contentFormat;

public String getContentFromFormat(Object... arguments) {
return MessageFormat.format(contentFormat, arguments);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@
import com.prgrms.nabmart.domain.notification.NotificationType;
import com.prgrms.nabmart.domain.notification.controller.request.ConnectNotificationCommand;
import com.prgrms.nabmart.domain.notification.repository.EmitterRepository;
import com.prgrms.nabmart.domain.notification.repository.NotificationRepository;
import com.prgrms.nabmart.domain.notification.service.request.SendNotificationCommand;
import com.prgrms.nabmart.domain.notification.service.response.NotificationResponse;
import com.prgrms.nabmart.domain.user.exception.NotFoundUserException;
import com.prgrms.nabmart.domain.user.repository.UserRepository;
import jakarta.transaction.Transactional;
import java.io.IOException;
import java.util.Map;
import lombok.RequiredArgsConstructor;
Expand All @@ -27,7 +25,6 @@ public class NotificationService {
private static final Long DEFAULT_TIMEOUT = 60L * 1000 * 120;

private final EmitterRepository emitterRepository;
private final NotificationRepository notificationRepository;
private final UserRepository userRepository;

public SseEmitter connectNotification(ConnectNotificationCommand connectNotificationCommand) {
Expand Down Expand Up @@ -65,20 +62,20 @@ private void send(SseEmitter emitter, String emitterId, Object data) {
log.error("알림 전송에 실패했습니다.", ex);
}
}

@Transactional

public void sendNotification(SendNotificationCommand sendNotificationCommand) {
Long userId = sendNotificationCommand.userId();
String title = sendNotificationCommand.title();
String content = sendNotificationCommand.content();
NotificationType notificationType = sendNotificationCommand.notificationType();

verifyExistsUser(userId);
Notification notification = Notification.builder()
.title(title)
.content(content)
.userId(userId)
.notificationType(notificationType)
.build();
notificationRepository.save(notification);

Map<String, SseEmitter> emitters = emitterRepository.findAllByIdStartWith(userId);
emitters.forEach((key, emitter) -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@

public record SendNotificationCommand(
Long userId,
String title,
String content,
NotificationType notificationType) {

public static SendNotificationCommand of(
final Long userId,
final String title,
final String content,
final NotificationType notificationType) {
return new SendNotificationCommand(userId, content, notificationType);
return new SendNotificationCommand(userId, title, content, notificationType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
import java.time.LocalDateTime;

public record NotificationResponse(
Long notificationId,
String title,
String content,
NotificationType notificationType,
Long userId,
LocalDateTime createdAt) {

public static NotificationResponse from(Notification notification) {
return new NotificationResponse(
notification.getNotificationId(),
notification.getTitle(),
notification.getContent(),
notification.getNotificationType(),
notification.getUserId(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import com.prgrms.nabmart.domain.delivery.service.response.FindRiderDeliveriesResponse.FindRiderDeliveryResponse;
import com.prgrms.nabmart.domain.delivery.service.response.FindWaitingDeliveriesResponse;
import com.prgrms.nabmart.domain.delivery.support.DeliveryFixture;
import com.prgrms.nabmart.domain.notification.service.NotificationService;
import com.prgrms.nabmart.domain.order.Order;
import com.prgrms.nabmart.domain.order.exception.NotFoundOrderException;
import com.prgrms.nabmart.domain.order.repository.OrderRepository;
Expand Down Expand Up @@ -75,6 +76,9 @@ class DeliveryServiceTest {
@Mock
OrderRepository orderRepository;

@Mock
NotificationService notificationService;

User user = UserFixture.user();
Order order = deliveringOrder(1L, user);
Rider rider = DeliveryFixture.rider();
Expand Down Expand Up @@ -106,6 +110,7 @@ void success() {

//then
then(deliveryRepository).should().save(any());
then(notificationService).should().sendNotification(any());
}

@Test
Expand Down Expand Up @@ -262,6 +267,24 @@ void success() {
assertThat(delivery.getDeliveryStatus()).isEqualTo(DeliveryStatus.START_DELIVERY);
}

@Test
@DisplayName("성공: 배달 시작 알림 전송")
void successThenNotify() {
//given
int deliveryEstimateMinutes = 20;
StartDeliveryCommand startDeliveryCommand
= StartDeliveryCommand.of(1L, deliveryEstimateMinutes, 1L);

given(riderRepository.findById(any())).willReturn(Optional.ofNullable(rider));
given(deliveryRepository.findById(any())).willReturn(Optional.ofNullable(delivery));

//when
deliveryService.startDelivery(startDeliveryCommand);

//then
then(notificationService).should().sendNotification(any());
}

@Test
@DisplayName("예외: 존재하지 않는 라이더")
void throwExceptionWhenNotFoundRider() {
Expand Down Expand Up @@ -349,6 +372,20 @@ void success() {
assertThat(delivery.getDeliveryStatus()).isEqualTo(DeliveryStatus.DELIVERED);
}

@Test
@DisplayName("성공: 배달 완료 알림 전송")
void successThenNotify() {
//given
given(riderRepository.findById(any())).willReturn(Optional.ofNullable(rider));
given(deliveryRepository.findById(any())).willReturn(Optional.ofNullable(delivery));

//when
deliveryService.completeDelivery(completeDeliveryCommand);

//then
then(notificationService).should().sendNotification(any());
}

@Test
@DisplayName("예외: 존재하지 않는 라이더")
void throwExceptionWhenNotFoundRider() {
Expand Down
Loading

0 comments on commit 3c2e596

Please sign in to comment.