2021. 12. 8. 16:52ㆍ스프링부트
주문 시 db에 저장 할 주문 정보는 order테이블에 메뉴정보는 order_detail테이블에 json으로 저장합니다
json을 편하게 변환하기 위해 gson라이브러리를 사용하겠습니다
<!-- json 변환 -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
저장 후 maven 업데이트를 해도 에러가 뜰때가 있는데 이럴땐 서버를 완전히 종료 후 재실행하면 적용됩니다
메뉴 정보를 담을 클래스를 생성합니다
@Getter
@Setter
@ToString
@AllArgsConstructor
public class OrderDetail {
private String orderNum;
private String foodInfoJSON;
}
OrderController payment메서드의 주문처리 부분을 주석 해제하고 service, dao를 추가합니다
orderService
public String order(CartList cart, OrderInfo info, LoginService user, HttpSession session);
orderServiceImp
@Transactional
@Override
public String order(CartList cart, OrderInfo info, LoginService user, HttpSession session) {
Gson gson = new Gson();
System.out.println("info = " + info);
int total = cart.getCartTotal();
info.setStoreId(cart.getStoreId());
info.setTotalPrice(total);
long userId = 0;
if (user != null) {
userId = user.getUser().getId();
info.setUserId(userId);
}
List<Cart> cartList = cart.getCart();
OrderDetail[] detail = new OrderDetail[cartList.size()];
for(int i=0;i<detail.length;i++) {
String cartJSON = gson.toJson(cartList.get(i));
detail[i] = new OrderDetail(info.getOrderNum(), cartJSON);
}
orderDAO.order(info);
orderDAO.orderDetail(detail, userId);
return null;
}
주문정보와 메뉴정보를 db에 입력하다 에러가 날 경우 전부 취소하기 위해 @Transactional를 붙여줍니다
orderDAO
// 주문 정보 입력
void order(OrderInfo info);
// 주문 상세정보 입력
void orderDetail(OrderDetail[] detail, long userId);
orderDAOImp
@Override
public void order(OrderInfo info) {
sql.insert("order.order", info);
}
@Override
public void orderDetail(OrderDetail[] detail, long userId) {
Map<String, Object> map = new HashMap<>();
map.put("userId", userId);
map.put("detail", detail);
sql.insert("order.orderDetail", map);
}
orderMappler.xml
<insert id="order">
<if test="userId == 0">
INSERT INTO BM_ORDER_NON_USER (
ORDER_NUM
,STORE_ID
,USER_ID
,PAY_METHOD
,PHONE
,DELEVERY_ADDRESS1
,DELEVERY_ADDRESS2
,DELEVERY_ADDRESS3
,TOTAL_PRICE
,USED_POINT
,REQUEST
) VALUES (
${orderNum }
,#{storeId }
,#{userId }
,#{payMethod }
,#{phone }
,#{deleveryAddress1 }
,#{deleveryAddress2 }
,#{deleveryAddress3 }
,#{totalPrice }
,#{usedPoint }
,#{request }
)
</if>
<if test="userId != 0">
INSERT INTO BM_ORDER_USER (
ORDER_NUM
,STORE_ID
,USER_ID
,PAY_METHOD
,PHONE
,DELEVERY_ADDRESS1
,DELEVERY_ADDRESS2
,DELEVERY_ADDRESS3
,TOTAL_PRICE
,USED_POINT
,REQUEST
) VALUES (
${orderNum }
,#{storeId }
,#{userId }
,#{payMethod }
,#{phone }
,#{deleveryAddress1 }
,#{deleveryAddress2 }
,#{deleveryAddress3 }
,#{totalPrice }
,#{usedPoint }
,#{request }
)
</if>
</insert>
insert all문은 하나의 쿼리로 insert를 여러번 할 수 있는데 select문의 들어가야 하기 때문에 SELECT * FROM DUAL을 붙여 주었습니다
실행 결과
로그인 이용자는 주문 완료 시 포인트 적립이 되야 합니다
OrderServiceImp의 order메서드 아래에 코드를 추가합니다
// 회원 포인트 적립
if (user != null) {
String storeName = cart.getStoreName();
int point = (int)(total * 0.01);
int result = adminDAO.pointUpdate(userId, storeName, point);
if(result == 1) {
UserInfoSessionUpdate.sessionUpdate(point+"", "point", user, session);
}
}
포인트 업데이트 관련 메서드는 adminDAO를 따로 만들어서 추가하겠습니다
OrderServiceImp에 의존성을 추가하고 adminDAO를 생성합니다
@Autowired
private AdminDAO adminDAO;
public interface AdminDAO {
int pointUpdate(long userId, String info, int point);
}
@Repository
public class AdminDAOImp implements AdminDAO {
@Autowired
private SqlSession sql;
@Override
public int pointUpdate(long userId, String info, int point) {
Map<String, Object> map = new HashMap<>();
map.put("userId", userId);
map.put("info", info);
map.put("point", point);
return sql.insert("admin.pointUpdate", map);
}
}
adminMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="admin">
<insert id="pointUpdate" >
INSERT INTO BM_POINT (
USER_ID
,INFO
,POINT
) VALUES (
#{userId }
,#{info }
,#{point }
)
</insert>
</mapper>
이제 db에는 포인트가 업데이트 되지만 아직 세션이 업데이트되지 않아 재로그인 하기 전까진 포인트사용을 할 수 없습니다
세션 업데이트를 위해 util패키지에 클래스를 추가합니다
public class UserInfoSessionUpdate {
public static void sessionUpdate(String value, String valueType, LoginService user, HttpSession session) {
LoginService loginService = (LoginService) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if(valueType.equals("nickname")) {
loginService.getUser().setNickname(value);
}
else if(valueType.equals("password")) {
loginService.getUser().setPassword(value);
}
else if(valueType.equals("point")) {
int point = loginService.getUser().getPoint() + Integer.parseInt(value);
loginService.getUser().setPoint(point);
}
SecurityContext sc = SecurityContextHolder.getContext();
sc.setAuthentication(new UsernamePasswordAuthenticationToken(loginService, null, user.getAuthorities()));
session.setAttribute("SPRING_SECURITY_CONTEXT", sc);
}
}
나중에 구현할 닉네임, 비밀번호 업데이트 코드를 미리 추가했습니다
이제 주문시 포인트가 적립되는 걸 볼 수 있습니다
-- 그런데 이 기능은 주문 시가 아니라 가게에서 주문을 수락하고 배달 완료가 될 때 적립되도록 변경 하는게 좋을거같습니다
마찬가지로 포인트를 사용하면 포인트가 차감되야 합니다
OrderServiceImp의 order메서드 아래에 코드를 추가합니다
// 로그인 사용자가 포인트 사용했을때
if(info.getUsedPoint() != 0 ) {
String storeName = cart.getStoreName();
int usedPoint = -info.getUsedPoint();
int result = adminDAO.pointUpdate(userId, storeName, usedPoint);
if(result == 1) {
UserInfoSessionUpdate.sessionUpdate(usedPoint+"", "point", user, session);
}
}
실행 결과
주문 완료후 주문 목록을 보기 위해 Controller에 추가합니다
@GetMapping("/orderList")
public String orderList(@AuthenticationPrincipal LoginService user, Model model) {
if (user == null) {
System.out.println("비로그인");
} else {
System.out.println("로그인");
long userId = user.getUser().getId();
List<OrderList> orderList = orderService.orderList(userId);
if (orderList.size() == 0) {
return "order/orderList";
}
List<List<Cart>> cartList = new ArrayList<>();
for (int i=0;i<orderList.size();i++) {
cartList.add(FoodInfoFromJson.foodInfoFromJson(orderList.get(i).getFoodInfo()));
}
model.addAttribute("user", user.getUser());
model.addAttribute("cartList", cartList);
model.addAttribute("orderList", orderList);
}
return "order/orderList";
}
service, dao를 추가합니다
orderService
// 주문목록
List<OrderList> orderList(long userId);
orderServiceImp
@Override
public List<OrderList> orderList(long userId) {
return orderDAO.orderList(userId);
}
orderDAO
List<OrderList> orderList(long userId);
orderDAOImp
@Override
public List<OrderList> orderList(long userId) {
return sql.selectList("order.orderList", userId);
}
orderMapper.xml
<select id="orderList" resultType="OrderList">
SELECT * FROM (
SELECT ROWNUM R
,O.*
FROM (SELECT count(*) over() list_count,
o.order_num,
o.user_id,
o.order_date,
o.pay_method,
o.delevery_status,
o.delevery_address1,
o.delevery_address2,
o.delevery_address3,
o.store_id,
o.total_price,
o.used_point,
o.request,
d.food_info,
s.store_name,
s.store_img,
s.store_thumb,
s.delevery_tip,
r.review_content,
r.score,
r.review_img
FROM bm_order_user o
LEFT JOIN (SELECT ORDER_NUM,
LISTAGG(FOOD_INFO, '/') food_info
FROM BM_ORDER_DETAIL_USER
GROUP BY ORDER_NUM) d
ON o.order_num = d.order_num
LEFT JOIN bm_store s
ON o.store_id = s.id
LEFT JOIN bm_review r
ON o.order_num = r.order_num
WHERE o.user_id = #{userId }
ORDER BY o.order_date desc
) O
)
</select>
listagg는 첫번 째 인자의 결과가 여러개가 있을 때 두번 째 인자의 구분자로 합쳐서 하나의 컬럼으로 보여줍니다
listagg 사용x
listagg 사용o
불러온 json형태의 메뉴 정보를 오브젝트로 변환하기 위해 util패키지에 추가합니다
public class FoodInfoFromJson {
public static List<Cart> foodInfoFromJson(String foodInfoJSON) {
Map<String, Object> map = new HashMap<>();
String[] arr = foodInfoJSON.split("/");
Gson gson = new Gson();
List<Cart> cartList = new ArrayList<>();
for(int i=0;i<arr.length;i++) {
cartList.add(gson.fromJson(arr[i], Cart.class));
}
return cartList;
}
}
이제 화면을 보여줄 jsp,css와 js를 추가합니다
리뷰 모달에서 이미지 첨부시 미리보기 기능을 위해 util.js에 코드를 추가합니다
function imgPreview(e,target){
const previewBox = target.siblings("div");
const preview = previewBox.find(".preview");
const fileReader = new FileReader();
fileReader.readAsDataURL(e.target.files[0]);
fileReader.onload = function() {
preview.attr("src", fileReader.result);
previewBox.css("display", "block");
}
}
function imgClose() {
$(".preview").attr("src", "");
$(".img").val("");
$(".img_box div").css("display", "none");
}
실행 결과
'스프링부트' 카테고리의 다른 글
스프링부트+jsp로 배달사이트 만들기-16 리뷰 사진 올리기 (0) | 2021.12.09 |
---|---|
스프링부트+jsp로 배달사이트 만들기-15 리뷰작성 (0) | 2021.12.08 |
스프링부트+jsp로 배달사이트 만들기-12 가게 정보 탭 (0) | 2021.12.07 |
스프링부트+jsp로 배달사이트 만들기-11 장바구니추가, 삭제 (2) | 2021.12.07 |
스프링부트+jsp로 배달사이트 만들기-10 음식 목록 가져오기 (0) | 2021.12.07 |