SpringBoot 배달의민족-22 관리자페이지 구현 ( 주문접수 관리 )

hanteng·2022년 8월 1일
0

SpringBoot 배달의민족

목록 보기
22/27

오늘은 매장에 들어온 주문을 접수하거나 취소할수 있는 주문관리 페이지를
구현해보도록 하겠습니다. 주문관리 페이지의 경우 지난시간에 구현했던
내가 운영중인 특정매장 관리페이지에서 메뉴버튼을 통해 접근이 가능합니다
밑의 주소에서 파일을 받아 css, js, jsp파일을 추가해주세요
layout폴더안에 header.jsp에서는 관리자메뉴 주소만 변경하였습니다

배달의민족22 - 화면구성파일

이제 관리자가 주문접수페이지 주소에 접근할경우 order.jsp를 보여주기 위해
기존 AdminController에 다음의 코드를 추가해주세요

AdminController.java 추가코드

	//주문접수 페이지
    @GetMapping("/admin/management/order/{id}")
	public String order(@PathVariable long id) {
		return "admin/order";
	}

데이터를 가져올 필요도 model에 심어줄 필요도 없습니다. 화면을 구성하는 데이터는
페이지가 로딩될때 ajax와 api컨트롤러를 통해 비동기적으로 추가해줄것입니다

현재 주문관리 페이지에 접근하면 이러한 화면을 보실수 있습니다
우리는 주문의 상태를 4가지로 나눌겁니다. 고객이 맨처음 주문을 완료하면
접수대기상태가 되며 사장님을 해당 주문을 수락하거나 취소할수 있습니다
수락시 처리중으로 넘어가며 처리중탭에서 완료체크시 배달완료로 넘어갑니다
접수대기/처리중/주문취소/배달완료 탭을 클릭시 해당 탭의 상태값(키워드)이 서버로
넘어가며 그 키워드로 order테이블에서 delivery_status칼럼을 조회합니다

AdminApiController.java 추가코드

	//주문접수 리스트
	@GetMapping("/api/admin/management/orderList")
	public ResponseEntity<Map<String, Object>> orderList(long storeId, String list, int page) {
	 
		System.out.println(storeId);
		System.out.println(list);
		System.out.println("page = " + page);
		List<OrderListDto> orderListDto = adminService.orderList(storeId, list, page);
		
		Map<String, Object> map = new HashMap<>();
		List<List<CartDto>> menuList = new ArrayList<>();
		System.out.println(orderListDto);
		if(orderListDto.size() != 0 && orderListDto.get(0).getFoodInfo() != null) {
			for (int i=0;i<orderListDto.size();i++) {
				menuList.add(FoodInfoFromJson.foodInfoFromJson(orderListDto.get(i).getFoodInfo()));
			}
		}
		
		System.out.println(menuList);
		map.put("orderList", orderListDto);
		map.put("cartList", menuList);
		return ResponseEntity.ok().body(map);
	}
	
	
	//주문수락
	@PatchMapping("/api/admin/management/orderAccept")
	public ResponseEntity<String> orderAccept(String orderNum, long userId) {
		//			userId == 0 비회원
		adminService.orderAccept(orderNum, userId);
		
		return ResponseEntity.ok().body("주문접수완료");
	}
	
	//주문취소
	@PatchMapping("/api/admin/management/orderCancle")
	public ResponseEntity<String> orderCancle(OrderCancelDto orderCancelDto) {
		System.out.println(orderCancelDto.toString());
		adminService.orderCancel(orderCancelDto);
		return ResponseEntity.ok().body("주문취소완료");
	}
	
	//주문 완료
	@PatchMapping("/api/admin/management/orderComplete")
	public ResponseEntity<String> orderComplete(String orderNum, long userId) {
		//			userId == 0 비회원
		adminService.orderComplete(orderNum, userId);
		return ResponseEntity.ok().body("주문완료");
	}

주문접수리스트는 주문관리페이지에서 주문대기/처리중/주문취소/배달완료 탭 클릭시
해당 탭에 맞는 정보를 뿌려주기 위한 위한 메서드입니다. 무한스크롤 페이징처리를
위해 page를 파라메터로 가지며 list에는 주문대기 / 처리중 과 같은 키워드를 받아
테이블을 검색합니다. 일반사용자의 주문목록페이지에서와 마찬가지로 Json데이터를
object로 변환해주는 작업후 이차원리스트에 저장합니다

주문수락 / 주문취소 / 주문완료 모두 요청시 주문테이블의 Status를
Update해주기만 하면 됩니다. 주문접수처리의 경우 '배달중'으로
주문취소의 경우 '주문취소', 주문완료의 경우 '배달 완료'로 바꿔줍니다
이 3가지 경우 모두 같은 테이블의 같은컬럼값을 update하고 주문접수처리와
주문완료의 경우 파라메터도 같으므로 하나의 메서드로 합칠수 있지만
주문취소의 경우는 조금 다릅니다.

주문취소의 경우 파라메터로 OrderCancelDto를 하나 추가하여 사용하는데
그 이유는 나중에 외부결제Api를 추가하여 사용할때 주문취소를 하면
외부결제Api를 통해 결제된 내역 또한 취소해야하므로 그에 대한 정보를 남겨두기
위함입니다.

OrderCancelDto.java 전체코드

@Data
public class OrderCancelDto {
 
	private String OrderNum;
	private long userId;
	private int totaloPrice;
	private int usedPoint;
	private int deleveryTip;
	
	private String impUid; // 아임포트 결제번호
}

AdminService.java 추가코드

	//주문 목록 
	public List<OrderListDto> orderList(long storeId, String list, int page) {
		Page p = new Page(page,10);
		
		Map<String, Object> map = new HashMap<>();
		
		map.put("storeId", storeId);
		map.put("list", list);
		map.put("firstList", p.getFirstList());
		map.put("lastList", p.getLastList());
		return adminMapper.orderList(map);
	}
	
	//주문 수락
	public void orderAccept(String orderNum, long userId) {
		Map<String, Object> map = new HashMap<>();
		map.put("orderNum", orderNum);
		map.put("userId", userId);
		adminMapper.orderAccept(map);
	}

	// 주문 취소
	public void orderCancel(OrderCancelDto orderCancelDto) {
		adminMapper.orderCancle(orderCancelDto);
	}
	
	//주문 완료
	public void orderComplete(String orderNum, long userId) {
		Map<String, Object> map = new HashMap<>();
		map.put("orderNum", orderNum);
		map.put("userId", userId);
		adminMapper.orderComplete(map);
	}

AdminMapper.java 추가코드

	//주문목록
	public List<OrderListDto> orderList(Map<String, Object> map);
	
	//주문처리
	public void orderAccept(Map<String, Object> map);
	
	//주문취소
	public void orderCancle(OrderCancelDto orderCancelDto);
	
	//주문완료
	public void orderComplete(Map<String, Object> map);

AdminMapper.xml 추가코드

	<!--주문목록 -->
	<select id="orderList" resultType="com.han.delivery.dto.OrderListDto">
		WITH T_ORDER AS ( 
		    SELECT * FROM (
		    	SELECT * FROM DL_ORDER_USER UNION ALL SELECT * FROM DL_ORDER_NON_USER) WHERE STORE_ID = #{storeId }
		),
		T_DETAIL AS (
		    SELECT  ORDER_NUM, 
		            LISTAGG(FOOD_INFO, '/') FOOD_INFO
		    FROM DL_ORDER_DETAIL_USER N
		    GROUP BY    ORDER_NUM
		    UNION ALL
		    SELECT  ORDER_NUM, 
		            LISTAGG(FOOD_INFO, '/') FOOD_INFO
		    FROM DL_ORDER_DETAIL_NON_USER N
		    GROUP BY    ORDER_NUM
		)
		 SELECT   COUNT1
	              ,COUNT2
	              ,COUNT3
	              ,COUNT4
	              ,O.*
	              ,D.FOOD_INFO
	              ,S.STORE_NAME
	              ,S.DELIVERY_TIP
	      FROM (
	          SELECT  #{storeId } AS STORE_ID
	                          ,A.COUNT COUNT1
	                          ,B.COUNT COUNT2
	                          ,C.COUNT COUNT3
	                          ,D.COUNT COUNT4
	                  FROM    (SELECT COUNT(*) COUNT FROM T_ORDER WHERE DELIVERY_STATUS = '주문접수 대기 중') A,
	                          (SELECT COUNT(*) COUNT FROM T_ORDER WHERE DELIVERY_STATUS = '배달 준비 중') B,
	                          (SELECT COUNT(*) COUNT FROM T_ORDER WHERE DELIVERY_STATUS = '주문 취소') C,
	                          (SELECT COUNT(*) COUNT FROM T_ORDER WHERE DELIVERY_STATUS = '배달 완료') D
	      ) ORDER_COUNT
	      LEFT JOIN
	      (SELECT * FROM
	          (SELECT ROWNUM RN, T.* FROM (
	              SELECT * FROM T_ORDER WHERE DELIVERY_STATUS LIKE '${list }%' ORDER BY ORDER_DATE) T ) 
	       WHERE RN BETWEEN 1 AND #{lastList }
	       )O       
	      ON          ORDER_COUNT.STORE_ID = O.STORE_ID
	      LEFT JOIN   T_DETAIL D      
	      ON          O.ORDER_NUM  = D.ORDER_NUM
	      LEFT JOIN   DL_STORE S
	      ON          O.STORE_ID = S.ID
	      ORDER BY ORDER_DATE
	</select>
	
	<!-- 주문수락 -->
	<update id="orderAccept">
		<if test="userId == 0">
			UPDATE DL_ORDER_NON_USER SET
		</if>
		<if test="userId != 0">
			UPDATE DL_ORDER_USER SET
		</if>
			DELIVERY_STATUS = '배달 준비 중'
			WHERE ORDER_NUM = #{orderNum }
	</update>
	
	<!-- 주문취소 -->
	<update id="orderCancle">
		<if test="userId == 0">
			UPDATE DL_ORDER_NON_USER SET 
		</if>
		<if test="userId != 0">
			UPDATE DL_ORDER_USER SET
		</if>
			DELIVERY_STATUS = '주문 취소'
			WHERE ORDER_NUM = #{orderNum }
	</update>
	
	<!-- 배달완료 -->
	<update id="orderComplete">
		<if test="userId == 0">
			UPDATE DL_ORDER_NON_USER SET 
		</if>
		<if test="userId != 0">
			UPDATE DL_ORDER_USER SET
		</if>
			DELIVERY_STATUS = '배달 완료'
			WHERE ORDER_NUM = #{orderNum }
	</update>

주문목록 쿼리의 경우 좀 깁니다. 일단 with절에 대한 설명은 기존 주문목록페이지를
구현하면서 했었으니 생략하고 우리는 기존에 주문처리 구현을 할때 사용자가 회원인지
비회원인지에 따라 order_user테이블과 order_non_user테이블에 각각 데이터를 저장
했었습니다. 주문목록에서는 회원과 비회원의 주문목록을 모두 나타내어야 하므로
두 테이블을 합쳐줘야 합니다 따라서 union을 사용하여 두테이블을 합친 결과를
T_ORDER라는 이름의 임시테이블을 만들어 저장합니다

또한 주문의 상세 정보 또한 order_detail_user테이블과 order_detail_non_user
테이블에 각각 저장해줬으므로 이 두개의 테이블 또한 union을 사용하여 합친 결과를
T_DETAIL라는 임시테이블에 저장합니다 이때 LISTAGG를 사용하여 같은 주문번호를
가지는 행을 하나로 합쳐줍니다

이제 임시테이블인 T_ORDER에서 우리가 처음 말한 주문의 4가지 상태값을 WHERE절을
사용하여 각각의 상태에 대한 COUNT를 뽑아주고 입력받은 storeId도 추가하여
ORDER_COUNT라는 이름으로 저장합니다

현재 임시 테이블인 T_ORDER와 T_DETAIL은 1:1의 관계를 가지며 우리는 여기에
매장의 몇가지 정보 또한 필요합니다. T_ORDER에는 STORE_ID가 존재하므로
LEFT JOIN을 통해 T_ORDER 테이블과 T_DETAIL, STORE테이블을 모두 붙일수가
있습니다 이때 T_ORDER테이블에서 현재 사용자가 선택한 탭이 주문접수인지 처리중인지
주문취소인지에 따라 Like문을 실행하여야 하고 페이징처리를 위해 ROWNUM으로 한번더
감싸주고 O라는 이름으로 저장합니다

ORDER_COUNT와 위의 O 모두 STORE_ID가 존재하므로
LEFT JOIN을 해주고 O에는 ORDER_NUM도 존재하므로 T_DETAIL도 LEFT JOIN해줍니다
마지막으로 STORE_ID로 DL_STORE테이블도 JOIN 해주면 우리가 원하는 정보를
다 불러올수 있습니다

profile
이메일 : ehfvndcjstk@naver.com

0개의 댓글