Skip to content

Commit

Permalink
feat: 상품 주문과 식권 사용 기능 구현 (#46)
Browse files Browse the repository at this point in the history
* feat: 장바구니 추가 기능 구현 (#41)

* feat: 장바구니 조회 기능 구현 (#43)

* feat: 장바구니 추가 기능 구현

* feat: 장바구니 조회 기능 구현

* feat: 상품 주문과 식권 사용 기능 구현(상품 주문 시 포인트 소모는 todo) (#45)

* feat: 장바구니 추가 기능 구현

* feat: 장바구니 조회 기능 구현

* feat: 상품 주문과 식권 사용 기능 구현
  • Loading branch information
LEEJaeHyeok97 authored Nov 19, 2024
1 parent 347f018 commit 4691974
Show file tree
Hide file tree
Showing 9 changed files with 178 additions and 17 deletions.
4 changes: 4 additions & 0 deletions src/main/java/com/jangburich/domain/common/BaseEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,8 @@ public abstract class BaseEntity {
@Enumerated(value = EnumType.STRING)
@Column(name = "status")
private Status status = Status.ACTIVE;

public void updateStatus(Status status) {
this.status = status;
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
package com.jangburich.domain.order.application;

import com.amazonaws.services.kms.model.NotFoundException;
import com.jangburich.domain.common.Status;
import com.jangburich.domain.menu.domain.Menu;
import com.jangburich.domain.menu.domain.repository.MenuRepository;
import com.jangburich.domain.order.domain.Cart;
import com.jangburich.domain.order.domain.Orders;
import com.jangburich.domain.order.domain.repository.CartRepository;
import com.jangburich.domain.order.domain.repository.OrdersRepository;
import com.jangburich.domain.order.dto.request.AddCartRequest;
import com.jangburich.domain.order.dto.request.OrderRequest;
import com.jangburich.domain.order.dto.response.CartResponse;
import com.jangburich.domain.order.dto.response.CartResponse.GetCartItemsResponse;
import com.jangburich.domain.order.dto.response.GetCartItemsResponse;
import com.jangburich.domain.store.domain.Store;
import com.jangburich.domain.store.domain.repository.StoreRepository;
import com.jangburich.domain.team.domain.Team;
import com.jangburich.domain.team.domain.repository.TeamRepository;
import com.jangburich.domain.user.domain.User;
import com.jangburich.domain.user.domain.repository.UserRepository;
import com.jangburich.global.payload.Message;
Expand All @@ -27,6 +34,8 @@ public class OrderService {
private final UserRepository userRepository;
private final MenuRepository menuRepository;
private final StoreRepository storeRepository;
private final OrdersRepository ordersRepository;
private final TeamRepository teamRepository;

@Transactional
public Message addCart(String userProviderId, AddCartRequest addCartRequest) {
Expand All @@ -46,7 +55,7 @@ public Message addCart(String userProviderId, AddCartRequest addCartRequest) {

if (optionalCart.isPresent()) {
Cart existingCart = optionalCart.get();
existingCart.updateQuantity(addCartRequest.quantity());
existingCart.updateQuantity(existingCart.getQuantity() + addCartRequest.quantity());

return Message.builder()
.message("장바구니에 상품을 추가했습니다.")
Expand All @@ -72,7 +81,7 @@ public CartResponse getCartItems(String userProviderId) {
User user = userRepository.findByProviderId(userProviderId)
.orElseThrow(() -> new NullPointerException());

List<Cart> carts = cartRepository.findAllByUser(user);
List<Cart> carts = cartRepository.findAllByUserAndStatus(user, Status.ACTIVE);

if (carts.isEmpty()) {
return CartResponse.of(List.of(), 0);
Expand All @@ -92,4 +101,92 @@ public CartResponse getCartItems(String userProviderId) {

return cartResponse;
}

@Transactional
public Message order(String userProviderId, OrderRequest orderRequest) {
User user = userRepository.findByProviderId(userProviderId)
.orElseThrow(() -> new NullPointerException());

Store store = storeRepository.findById(orderRequest.storeId())
.orElseThrow(() -> new IllegalArgumentException("유효하지 않은 가게 id 입니다."));

Team team = teamRepository.findById(orderRequest.teamId())
.orElseThrow(() -> new IllegalArgumentException("유효하지 않은 그룹 id 입니다."));

List<Cart> existingCarts = cartRepository.findAllByUserAndStore(user, store);

List<Cart> mergedCarts = mergeCarts(existingCarts, orderRequest.items(), user, store);


Orders orders = saveOrder(user, store, team, orderRequest);

associateCartsWithOrder(mergedCarts, orders);

cartRepository.saveAll(mergedCarts);

return Message.builder()
.message("주문이 완료되었습니다.")
.build();
}

private List<Cart> mergeCarts(List<Cart> existingCarts, List<OrderRequest.OrderItemRequest> items, User user, Store store) {
for (OrderRequest.OrderItemRequest item : items) {
Optional<Cart> existingCart = findCartByMenuId(existingCarts, item.menuId());
if (existingCart.isPresent()) {
existingCart.get().updateQuantity(existingCart.get().getQuantity() + item.quantity());
existingCart.get().updateStatus(Status.INACTIVE);
continue;
}
Cart newCart = createNewCart(item, user, store);
existingCarts.add(newCart);
}
return existingCarts;
}

private Optional<Cart> findCartByMenuId(List<Cart> carts, Long menuId) {
return carts.stream()
.filter(cart -> cart.getMenu().getId().equals(menuId))
.findFirst();
}

private Cart createNewCart(OrderRequest.OrderItemRequest item, User user, Store store) {
Menu menu = menuRepository.findById(item.menuId())
.orElseThrow(() -> new IllegalArgumentException("유효하지 않은 메뉴 ID입니다."));
return Cart.builder()
.quantity(item.quantity())
.menu(menu)
.user(user)
.store(store)
.orders(null)
.build();
}

private Orders saveOrder(User user, Store store, Team team, OrderRequest orderRequest) {
Orders orders = Orders.builder()
.store(store)
.user(user)
.team(team)
.build();
return ordersRepository.save(orders);
}

private void associateCartsWithOrder(List<Cart> carts, Orders orders) {
carts.forEach(cart -> cart.updateOrders(orders));
}

public Message useMealTicket(String userProviderId, Long orderId) {
User user = userRepository.findByProviderId(userProviderId)
.orElseThrow(() -> new NullPointerException());

Orders orders = ordersRepository.findById(orderId)
.orElseThrow(() -> new NotFoundException("식권을 찾을 수 없습니다"));

orders.validateUser(user);

orders.updateStatus(Status.INACTIVE);

return Message.builder()
.message("식권을 사용했습니다.")
.build();
}
}
6 changes: 5 additions & 1 deletion src/main/java/com/jangburich/domain/order/domain/Cart.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ public Cart(Integer quantity, Orders orders, Menu menu, User user, Store store)
}

public void updateQuantity(int quantity) {
this.quantity += quantity;
this.quantity = quantity;
}

public void updateOrders(Orders orders) {
this.orders = orders;
}
}
15 changes: 15 additions & 0 deletions src/main/java/com/jangburich/domain/order/domain/Orders.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

Expand All @@ -37,4 +38,18 @@ public class Orders extends BaseEntity {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "team_id")
private Team team;


@Builder
public Orders(Store store, User user, Team team) {
this.store = store;
this.user = user;
this.team = team;
}

public void validateUser(User user) {
if (!this.user.equals(user)) {
throw new IllegalArgumentException("유저 정보가 일치하지 않습니다.");
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.jangburich.domain.order.domain.repository;

import com.jangburich.domain.common.Status;
import com.jangburich.domain.order.domain.Cart;
import com.jangburich.domain.store.domain.Store;
import com.jangburich.domain.user.domain.User;
import java.util.List;
import java.util.Optional;
Expand All @@ -14,5 +16,7 @@ public interface CartRepository extends JpaRepository<Cart, Long> {
@Query("SELECT c FROM Cart c WHERE c.user.userId = :userId AND c.menu.id = :menuId")
Optional<Cart> findByUserIdAndMenuId(@Param("userId") Long userId, @Param("menuId") Long menuId);

List<Cart> findAllByUser(User user);
List<Cart> findAllByUserAndStore(User user, Store store);

List<Cart> findAllByUserAndStatus(User user, Status status);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.jangburich.domain.order.dto.request;

import java.util.List;

public record OrderRequest(
Long storeId,
Long teamId,
List<OrderItemRequest> items
) {
public static record OrderItemRequest(
Long menuId,
Integer quantity
) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public record CartResponse(
) {
public static CartResponse of(List<GetCartItemsResponse> cartItems, Integer discountAmount) {
int totalAmount = cartItems.stream()
.mapToInt(item -> item.menuPrice * item.quantity)
.mapToInt(item -> item.menuPrice() * item.quantity())
.sum();

discountAmount = 0;
Expand All @@ -20,14 +20,4 @@ public static CartResponse of(List<GetCartItemsResponse> cartItems, Integer disc
return new CartResponse(cartItems, totalAmount, discountAmount, finalAmount);
}

public record GetCartItemsResponse(
String menuName,
String menuDescription,
Integer quantity,
Integer menuPrice
) {
public static GetCartItemsResponse of(String menuName, String menuDescription, Integer quantity, Integer menuPrice) {
return new GetCartItemsResponse(menuName, menuDescription, quantity, menuPrice);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.jangburich.domain.order.dto.response;

public record GetCartItemsResponse(
String menuName,
String menuDescription,
Integer quantity,
Integer menuPrice
) {
public static GetCartItemsResponse of(String menuName, String menuDescription, Integer quantity,
Integer menuPrice) {
return new GetCartItemsResponse(menuName, menuDescription, quantity, menuPrice);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.jangburich.domain.order.application.OrderService;
import com.jangburich.domain.order.dto.request.AddCartRequest;
import com.jangburich.domain.order.dto.request.OrderRequest;
import com.jangburich.domain.order.dto.response.CartResponse;
import com.jangburich.global.payload.Message;
import com.jangburich.global.payload.ResponseCustom;
Expand All @@ -11,6 +12,7 @@
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.GetMapping;
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;
Expand Down Expand Up @@ -40,4 +42,21 @@ public ResponseCustom<CartResponse> getCartItems(
) {
return ResponseCustom.OK(orderService.getCartItems(AuthenticationParser.parseUserId(authentication)));
}
}

@Operation(summary = "상품 주문", description = "상품을 주문합니다.")
@PostMapping
public ResponseCustom<Message> order(
Authentication authentication,
@RequestBody OrderRequest orderRequest
) {
return ResponseCustom.OK(orderService.order(AuthenticationParser.parseUserId(authentication), orderRequest));
}

@Operation(summary = "식권 사용", description = "식권을 사용합니다.")
public ResponseCustom<Message> useMealTicket(
Authentication authentication,
@PathVariable Long orderId
) {
return ResponseCustom.OK(orderService.useMealTicket(AuthenticationParser.parseUserId(authentication), orderId));
}
}

0 comments on commit 4691974

Please sign in to comment.