카테고리 없음

TIL 2024-12-06 (outsourcing 3일차)

myoma 2024. 12. 6. 23:30

1) 프로젝트 진행도

  • 가게 CRUD 구현
    • 가게 생성
    • 가게 수정
    • 가게 단건 조회(메뉴 같이 조회)
    • 가게 이름 검색(이름으로 검색히 연관된 가게 다 조회)
    • 가게 페업
  • 메뉴 CRUD 구현
    • 메뉴 생성 (1일차)
    • 메뉴 삭제
    • 메뉴 수정 (2일차)
  • 장바구니 (쿠키 활용)
    • 장바구니 메뉴 추가
    • 장바구니 메뉴 주문 처리 (3일차)

 


  • 장바구니 메뉴 추가
 public List<BasketItemDto> addBasket(OrderRequestDto requestDto, Cookie basketCookie, HttpServletResponse response) {

        List<BasketItemDto> basket = parseBasketFromCookie(basketCookie);

        //메뉴 가져오기
        Menu menu = menuRepository.findByMenuOrElseThrow(requestDto.getMenuId());

        //한 가게의 메뉴만 허용
        if(!basket.isEmpty() && !basket.get(0).getStoreId().equals(menu.getStore().getId())) {
            // 다른 가게 메뉴가 담긴 경우 초기화
            basket.clear();
        }

        //장바구니에 메뉴 넣기
        BasketItemDto basketItem = new BasketItemDto(
                menu.getId(),
                menu.getStore().getId(),
                requestDto.getCount()
        );

        basket.add(basketItem);
        //쿠키에 저장
        saveBasketToCookie(basket, response);

        return basket;
    }
  • 장바구니에 메뉴를 추가하는 서비스 로직
    • 맨 처음 JSON 형태로 데이터를 받기 위해 파싱을 진행.
    • 다른 가게의 메뉴를 가져오면 basket이 초기화 되도록 조건.
    • 메뉴를 계속 saveBasketToCookie에 저장.

 

 

  • 장바구니 주문 처리
@Transactional
    public OrderResponseDto basketOrder(User loginUser, Cookie basketCookie, HttpServletResponse response) {

        List<BasketItemDto> basket = parseBasketFromCookie(basketCookie);
        List<Store> stores = new ArrayList<>();

        if (basket.isEmpty()) {
            throw new CustomException(ErrorCode.EMPTY_BASKET);
        }

        // 주문 생성
        Orders order = new Orders(loginUser,OrderStep.ORDER_COMPLETED);
        Orders savedOrder = orderRepository.save(order);

        for (BasketItemDto basketItem : basket) {
            Menu menu = menuRepository.findByMenuOrElseThrow(basketItem.getMenuId());

            Store store = menu.getStore();
            stores.add(store);

            orderMenuRepository.insertOrderMenu(savedOrder.getId(), menu.getId(), basketItem.getCount());

        }
        List<OrderDto> ordersList = orderMenuRepository.getOrderMenus(savedOrder.getId());
        Integer totalPrice = ((BigDecimal) orderMenuRepository.findTotalPrice(savedOrder.getId())).intValue();


        // 총 가격 업데이트
        orderRepository.updateTotalPrice(totalPrice, savedOrder.getId());
        orderRepository.updateStore(stores.get(0), savedOrder.getId());
        // 장바구니 비우기
        clearBasketCookie(response);

        return OrderResponseDto.builder()
                .id(savedOrder.getId())
                .storeId(basket.get(0).getStoreId())
                .order(ordersList)
                .totalPrice(totalPrice)
                .createdAt(savedOrder.getCreatedAt())
                .build();

    }
  • 맨 처음 역시 파싱을 진행하여 JSON 데이터를 역직렬화를 통해 받기.

 

 

  • 주요 메서드들

 

  • 역직렬화 메서드
/**
     * 쿠키에서 장바구니 데이터를 읽어와 객체로 변환(역직렬화)
     * @param basketCookie
     * @return
     */
    private List<BasketItemDto> parseBasketFromCookie(Cookie basketCookie) {
        //쿠키가 없으면 빈 장바구니로 반환
        if (basketCookie == null) {
            return new ArrayList<>();
        }
        try {
            // URL 디코딩
            String decodedBasket = URLDecoder.decode(basketCookie.getValue(), "UTF-8");

            //JSON 문자열인 쿠키 값을 List<BasketItemDto>로 역직렬화, //제네릭 타입을 처리하기 위한 도구.
            return objectMapper.readValue(decodedBasket, new TypeReference<List<BasketItemDto>>() {});

        } catch (JsonProcessingException | UnsupportedEncodingException e) {
            throw new CustomException(ErrorCode.BAD_REQUEST);
        }
    }

 

  • 직렬화 메서드
/**
     * 장바구니 데이터를 JSON으로 직렬화하여 쿠키에 저장
     * @param basket
     * @param response
     */
    private void saveBasketToCookie(List<BasketItemDto> basket, HttpServletResponse response) {
        try {
            //List<BasketItemDto> 객체를 JSON 문자열로 직렬화
            String basketJson = objectMapper.writeValueAsString(basket);

            // URL 인코딩
            String encodedBasket = URLEncoder.encode(basketJson, "UTF-8");

            //직렬화된 JSON 데이터를 쿠키에 저장
            Cookie cookie = new Cookie("basket", encodedBasket);
            cookie.setMaxAge((int) COOKIE_MAX_AGE); // 쿠키 만료 시간 설정 (24시간)
            cookie.setHttpOnly(true); // JavaScript 접근 불가 설정
            cookie.setPath("/"); // 모든 경로에서 쿠키 접근 가능
            response.addCookie(cookie); // HTTP 응답에 쿠키 추가
        }
        catch (JsonProcessingException | UnsupportedEncodingException e ) {
            throw new CustomException(ErrorCode.BAD_REQUEST);
        }
    }

 

  • 장바구니 쿠키 삭제
/**
     * 장바구니 쿠키 삭제
     * @param response
     */
    private void clearBasketCookie(HttpServletResponse response) {
        Cookie cookie = new Cookie("basket", null); // 쿠키 값을 null로 설정
        cookie.setMaxAge(0); // 만료 시간을 0으로 설정 (즉시 삭제)
        cookie.setPath("/"); // 모든 경로에서 쿠키 삭제
        response.addCookie(cookie); // HTTP 응답에 쿠키 추가
    }

 

 

  • 장바구니 주문 처리에서의 주요 JPQL
    @Modifying
    @Query(value = "INSERT INTO order_menu(orders_Id, menu_id, food_count) VALUES (:orders_id, :menu_id, :food_count ) " , nativeQuery = true)
    void insertOrderMenu(@Param("orders_id") Long orders_id, @Param("menu_id") Long menu_id, @Param("food_count") Integer food_count);

    @Query(value = "SELECT new com.example.outsourcing.order.dto.OrderDto(om.menuId.id, om.menuId.menuName, om.foodCount) " +
            "FROM order_menu om where om.ordersId.id = :orders_id")
    List<OrderDto> getOrderMenus(@Param("orders_id") Long orders_id);


    @Query(value = "SELECT SUM(m.price * om.food_count) FROM order_menu om inner join menu m on om.menu_id = m.id WHERE om.orders_Id = :orders_id ", nativeQuery = true)
    Object findTotalPrice(@Param("orders_id") Long orders_id);

 

  • 코드들에 관한 설명은 다음 TIL에서 진행.