Skip to content

Commit

Permalink
Merge branch 'develop' into docs/api-docs
Browse files Browse the repository at this point in the history
  • Loading branch information
pushedrumex authored Sep 22, 2023
2 parents 0629641 + c539360 commit 5a62ecd
Show file tree
Hide file tree
Showing 74 changed files with 1,672 additions and 268 deletions.
17 changes: 16 additions & 1 deletion src/main/java/com/prgrms/nabmart/domain/delivery/Delivery.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.prgrms.nabmart.domain.delivery.exception.InvalidDeliveryException;
import com.prgrms.nabmart.domain.delivery.exception.UnauthorizedDeliveryException;
import com.prgrms.nabmart.domain.order.Order;
import com.prgrms.nabmart.domain.order.OrderStatus;
import com.prgrms.nabmart.domain.user.User;
import com.prgrms.nabmart.global.BaseTimeEntity;
import jakarta.persistence.Column;
Expand Down Expand Up @@ -68,14 +69,28 @@ public class Delivery extends BaseTimeEntity {
@Column
private Integer deliveryFee;

@Column
private Long userId;

@Builder
public Delivery(final Order order) {
public Delivery(final Order order, final int estimateMinutes) {
validateOrderStatus(order);
validateEstimateMinutes(estimateMinutes);
this.order = order;
this.deliveryStatus = DeliveryStatus.ACCEPTING_ORDER;
this.address = order.getAddress();
this.orderPrice = order.getPrice();
this.riderRequest = order.getRiderRequest();
this.deliveryFee = order.getDeliveryFee();
this.arrivedAt = LocalDateTime.now().plusMinutes(estimateMinutes);
this.userId = order.getUser().getUserId();
order.updateOrderStatus(OrderStatus.DELIVERING);
}

private void validateOrderStatus(Order order) {
if(!order.isPayed()) {
throw new InvalidDeliveryException("결제 완료된 주문이 아닙니다.");
}
}

public boolean isOwnByUser(final User user) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
package com.prgrms.nabmart.domain.delivery.controller;

import com.prgrms.nabmart.domain.delivery.controller.request.FindRiderDeliveriesRequest;
import com.prgrms.nabmart.domain.delivery.controller.request.RegisterDeliveryRequest;
import com.prgrms.nabmart.domain.delivery.controller.request.StartDeliveryRequest;
import com.prgrms.nabmart.domain.delivery.exception.AlreadyAssignedDeliveryException;
import com.prgrms.nabmart.domain.delivery.exception.DeliveryException;
import com.prgrms.nabmart.domain.delivery.service.DeliveryService;
import com.prgrms.nabmart.domain.delivery.service.request.AcceptDeliveryCommand;
import com.prgrms.nabmart.domain.delivery.service.request.CompleteDeliveryCommand;
import com.prgrms.nabmart.domain.delivery.service.request.FindDeliveryCommand;
import com.prgrms.nabmart.domain.delivery.service.request.FindDeliveryByOrderCommand;
import com.prgrms.nabmart.domain.delivery.service.request.FindDeliveryDetailCommand;
import com.prgrms.nabmart.domain.delivery.service.request.FindRiderDeliveriesCommand;
import com.prgrms.nabmart.domain.delivery.service.request.FindWaitingDeliveriesCommand;
import com.prgrms.nabmart.domain.delivery.service.request.RegisterDeliveryCommand;
import com.prgrms.nabmart.domain.delivery.service.request.StartDeliveryCommand;
import com.prgrms.nabmart.domain.delivery.service.response.FindDeliveryDetailResponse;
import com.prgrms.nabmart.domain.delivery.service.response.FindDeliveryByOrderResponse;
import com.prgrms.nabmart.domain.delivery.service.response.FindRiderDeliveriesResponse;
import com.prgrms.nabmart.domain.delivery.service.response.FindWaitingDeliveriesResponse;
import com.prgrms.nabmart.global.auth.LoginUser;
import com.prgrms.nabmart.global.util.ErrorTemplate;
import jakarta.validation.Valid;
import java.net.URI;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
Expand All @@ -26,6 +30,7 @@
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
Expand All @@ -35,15 +40,42 @@
@RequestMapping("/api/v1")
public class DeliveryController {

private static final String BASE_URI = "/api/v1/deliveries/";

private final DeliveryService deliveryService;

@PostMapping("/orders/{orderId}/deliveries")
public ResponseEntity<Void> registerDelivery(
@PathVariable final Long orderId,
@RequestBody final RegisterDeliveryRequest registerDeliveryRequest,
@LoginUser final Long userId) {
RegisterDeliveryCommand registerDeliveryCommand = RegisterDeliveryCommand.of(
orderId,
userId,
registerDeliveryRequest.estimateMinutes());
Long deliveryId = deliveryService.registerDelivery(registerDeliveryCommand);
URI location = URI.create(BASE_URI + deliveryId);
return ResponseEntity.created(location).build();
}

@GetMapping("/orders/{orderId}/deliveries")
public ResponseEntity<FindDeliveryDetailResponse> findDelivery(
public ResponseEntity<FindDeliveryByOrderResponse> findDeliveryByOrder(
@PathVariable final Long orderId,
@LoginUser final Long userId) {
FindDeliveryCommand findDeliveryCommand = FindDeliveryCommand.of(userId, orderId);
FindDeliveryDetailResponse findDeliveryDetailResponse
= deliveryService.findDelivery(findDeliveryCommand);
FindDeliveryByOrderCommand findDeliveryByOrderCommand
= FindDeliveryByOrderCommand.of(userId, orderId);
FindDeliveryByOrderResponse findDeliveryByOrderResponse
= deliveryService.findDeliveryByOrder(findDeliveryByOrderCommand);
return ResponseEntity.ok(findDeliveryByOrderResponse);
}

@GetMapping("/deliveries/{deliveryId}")
public ResponseEntity<FindDeliveryDetailResponse> findDelivery(
@PathVariable final Long deliveryId) {
FindDeliveryDetailCommand findDeliveryDetailCommand
= FindDeliveryDetailCommand.from(deliveryId);
FindDeliveryDetailResponse findDeliveryDetailResponse = deliveryService.findDelivery(
findDeliveryDetailCommand);
return ResponseEntity.ok(findDeliveryDetailResponse);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.prgrms.nabmart.domain.delivery.controller;

import com.prgrms.nabmart.domain.delivery.Delivery;
import com.prgrms.nabmart.domain.delivery.DeliveryStatus;
import com.prgrms.nabmart.domain.order.OrderItem;
import java.time.LocalDateTime;
import java.util.List;

public record FindDeliveryDetailResponse(
Long deliveryId,
DeliveryStatus deliveryStatus,
LocalDateTime arrivedAt,
String address,
String orderName,
int orderPrice,
String riderRequest,
int deliveryFee,
List<OrderItemResponse> items) {


public static FindDeliveryDetailResponse from(final Delivery delivery) {
List<OrderItemResponse> items = delivery.getOrder().getOrderItems().stream()
.map(OrderItemResponse::from)
.toList();
return new FindDeliveryDetailResponse(
delivery.getDeliveryId(),
delivery.getDeliveryStatus(),
delivery.getArrivedAt(),
delivery.getAddress(),
delivery.getOrder().getName(),
delivery.getOrderPrice(),
delivery.getRiderRequest(),
delivery.getDeliveryFee(),
items);
}

public record OrderItemResponse(String name, int quantity, int price) {

public static OrderItemResponse from(final OrderItem orderItem) {
return new OrderItemResponse(
orderItem.getItem().getName(),
orderItem.getQuantity(),
orderItem.getItem().getPrice());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.prgrms.nabmart.domain.delivery.controller.request;

import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;

public record RegisterDeliveryRequest(
@Positive(message = "배달 예상 소요 시간은 양수여야 합니다.")
@NotNull(message = "배달 예상 소요 시간은 필수입니다.")
Integer estimateMinutes) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.prgrms.nabmart.domain.delivery.exception;

public class AlreadyRegisteredDeliveryException extends DeliveryException {

public AlreadyRegisteredDeliveryException(final String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.prgrms.nabmart.domain.delivery.Delivery;
import com.prgrms.nabmart.domain.delivery.DeliveryStatus;
import com.prgrms.nabmart.domain.delivery.Rider;
import com.prgrms.nabmart.domain.order.Order;
import com.prgrms.nabmart.domain.user.User;
import jakarta.persistence.LockModeType;
import java.util.List;
Expand Down Expand Up @@ -38,4 +39,13 @@ Page<Delivery> findRiderDeliveries(

@Query("select d from Delivery d join d.order o where o.user = :user")
List<Delivery> findAllByUser(@Param("user") User user);

boolean existsByOrder(Order order);

@Query("select d from Delivery d"
+ " join fetch d.order o"
+ " join fetch o.orderItems oi"
+ " join fetch oi.item i"
+ " where d.deliveryId = :deliveryId")
Optional<Delivery> findByIdWithOrderAndItems(@Param("deliveryId") Long deliveryId);
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,38 @@
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.controller.FindDeliveryDetailResponse;
import com.prgrms.nabmart.domain.delivery.exception.AlreadyRegisteredDeliveryException;
import com.prgrms.nabmart.domain.delivery.exception.NotFoundDeliveryException;
import com.prgrms.nabmart.domain.delivery.exception.NotFoundRiderException;
import com.prgrms.nabmart.domain.delivery.exception.UnauthorizedDeliveryException;
import com.prgrms.nabmart.domain.delivery.repository.DeliveryRepository;
import com.prgrms.nabmart.domain.delivery.repository.RiderRepository;
import com.prgrms.nabmart.domain.delivery.service.request.AcceptDeliveryCommand;
import com.prgrms.nabmart.domain.delivery.service.request.CompleteDeliveryCommand;
import com.prgrms.nabmart.domain.delivery.service.request.FindDeliveryCommand;
import com.prgrms.nabmart.domain.delivery.service.request.FindDeliveryByOrderCommand;
import com.prgrms.nabmart.domain.delivery.service.request.FindDeliveryDetailCommand;
import com.prgrms.nabmart.domain.delivery.service.request.FindRiderDeliveriesCommand;
import com.prgrms.nabmart.domain.delivery.service.request.FindWaitingDeliveriesCommand;
import com.prgrms.nabmart.domain.delivery.service.request.RegisterDeliveryCommand;
import com.prgrms.nabmart.domain.delivery.service.request.StartDeliveryCommand;
import com.prgrms.nabmart.domain.delivery.service.response.FindDeliveryDetailResponse;
import com.prgrms.nabmart.domain.delivery.service.response.FindDeliveryByOrderResponse;
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;
import com.prgrms.nabmart.domain.user.User;
import com.prgrms.nabmart.domain.user.exception.NotFoundUserException;
import com.prgrms.nabmart.domain.user.repository.UserRepository;
import com.prgrms.nabmart.global.auth.exception.AuthorizationException;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
Expand All @@ -31,21 +45,84 @@ public class DeliveryService {
private final DeliveryRepository deliveryRepository;
private final UserRepository userRepository;
private final RiderRepository riderRepository;
private final OrderRepository orderRepository;
private final NotificationService notificationService;

@Transactional
public Long registerDelivery(RegisterDeliveryCommand registerDeliveryCommand) {
checkUserHasRegisterDeliveryAuthority(registerDeliveryCommand.userId());
Order order = findOrderByOrderIdPessimistic(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()) {
throw new UnauthorizedDeliveryException("권한이 없습니다.");
}
}

private Order findOrderByOrderIdPessimistic(RegisterDeliveryCommand registerDeliveryCommand) {
return orderRepository.findByIdPessimistic(registerDeliveryCommand.orderId())
.orElseThrow(() -> new NotFoundOrderException("존재하지 않는 주문입니다."));
}

private void checkAlreadyRegisteredDelivery(final Order order) {
if (deliveryRepository.existsByOrder(order)) {
throw new AlreadyRegisteredDeliveryException("이미 배달이 생성된 주문입니다.");
}
}

@Transactional(readOnly = true)
public FindDeliveryDetailResponse findDelivery(FindDeliveryCommand findDeliveryCommand) {
User user = findUserByUserId(findDeliveryCommand.userId());
Delivery delivery = findDeliveryByOrderWithOrder(findDeliveryCommand.orderId());
public FindDeliveryByOrderResponse findDeliveryByOrder(
FindDeliveryByOrderCommand findDeliveryByOrderCommand) {
User user = findUserByUserId(findDeliveryByOrderCommand.userId());
Delivery delivery = findDeliveryByOrderWithOrder(findDeliveryByOrderCommand.orderId());
checkAuthority(delivery, user);
return FindDeliveryDetailResponse.from(delivery);
return FindDeliveryByOrderResponse.from(delivery);
}

private void checkAuthority(final Delivery delivery, final User user) {
if (!delivery.isOwnByUser(user)) {
throw new AuthorizationException("권한이 없습니다.");
throw new UnauthorizedDeliveryException("권한이 없습니다.");
}
}

@Transactional(readOnly = true)
public FindDeliveryDetailResponse findDelivery(
FindDeliveryDetailCommand findDeliveryDetailCommand) {
Delivery delivery = findDeliveryByDeliveryIdWithOrderAndOrderItems(
findDeliveryDetailCommand);
return FindDeliveryDetailResponse.from(delivery);
}

private Delivery findDeliveryByDeliveryIdWithOrderAndOrderItems(
FindDeliveryDetailCommand findDeliveryDetailCommand) {
return deliveryRepository.findByIdWithOrderAndItems(
findDeliveryDetailCommand.deliveryId())
.orElseThrow(() -> new NotFoundDeliveryException("존재하지 않는 배달입니다."));
}

@Transactional
public void acceptDelivery(AcceptDeliveryCommand acceptDeliveryCommand) {
Rider rider = findRiderByRiderId(acceptDeliveryCommand.riderId());
Expand All @@ -65,6 +142,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 @@ -73,6 +163,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
@@ -0,0 +1,8 @@
package com.prgrms.nabmart.domain.delivery.service.request;

public record FindDeliveryByOrderCommand(Long userId, Long orderId) {

public static FindDeliveryByOrderCommand of(final Long userId,final Long orderId) {
return new FindDeliveryByOrderCommand(userId, orderId);
}
}

This file was deleted.

Loading

0 comments on commit 5a62ecd

Please sign in to comment.