Przeglądaj źródła

Merge remote-tracking branch 'origin/order' into jsh77b

jsh77b 5 lat temu
rodzic
commit
8684a01c3d
27 zmienionych plików z 2326 dodań i 1056 usunięć
  1. 5 1
      pom.xml
  2. 12 0
      src/main/java/com/style24/front/biz/dao/TsfCouponDao.java
  3. 13 0
      src/main/java/com/style24/front/biz/dao/TsfCustomerDao.java
  4. 1 3
      src/main/java/com/style24/front/biz/service/TsfCartService.java
  5. 36 5
      src/main/java/com/style24/front/biz/service/TsfCouponService.java
  6. 165 9
      src/main/java/com/style24/front/biz/service/TsfCustomerService.java
  7. 116 21
      src/main/java/com/style24/front/biz/thirdparty/KaKaoLogin.java
  8. 28 11
      src/main/java/com/style24/front/biz/thirdparty/NaverLogin.java
  9. 1 1
      src/main/java/com/style24/front/biz/web/TsfCartController.java
  10. 33 31
      src/main/java/com/style24/front/biz/web/TsfCustomerController.java
  11. 151 0
      src/main/java/com/style24/front/biz/web/TsfIndexController.java
  12. 136 2
      src/main/java/com/style24/front/biz/web/TsfMypageController.java
  13. 3 0
      src/main/java/com/style24/persistence/domain/Coupon.java
  14. 38 0
      src/main/java/com/style24/persistence/domain/CustSnsInfo.java
  15. 58 0
      src/main/java/com/style24/persistence/mybatis/shop/TsfCoupon.xml
  16. 69 0
      src/main/java/com/style24/persistence/mybatis/shop/TsfCustomer.xml
  17. 1 0
      src/main/java/com/style24/persistence/mybatis/shop/TsfOrder.xml
  18. 14 14
      src/main/resources/config/application.yml
  19. 4 0
      src/main/resources/i18n/messages/message_ko_KR.properties
  20. 31 16
      src/main/webapp/WEB-INF/views/web/SigninFormWeb.html
  21. 48 0
      src/main/webapp/WEB-INF/views/web/SnsCallBackFormWeb.html
  22. 891 917
      src/main/webapp/WEB-INF/views/web/cart/cartListAjaxFormWeb.html
  23. 6 12
      src/main/webapp/WEB-INF/views/web/mypage/MypageExchangeFormWeb.html
  24. 65 10
      src/main/webapp/WEB-INF/views/web/mypage/MypageOrderListFormWeb.html
  25. 335 0
      src/main/webapp/WEB-INF/views/web/mypage/MypageReturnFormWeb.html
  26. 11 1
      src/main/webapp/ux/pc/js/cart.js
  27. 55 2
      src/main/webapp/ux/style24_link.js

+ 5 - 1
pom.xml

@@ -59,7 +59,11 @@
 			<artifactId>commons-io</artifactId>
 			<version>2.6</version>
 		</dependency>
-		
+		<dependency>
+			<groupId>com.googlecode.libphonenumber</groupId>
+			<artifactId>libphonenumber</artifactId>
+			<version>8.12.16</version>
+		</dependency>
 		<!-- /// WEB-INF lib -->
 		<dependency>
 			<groupId>com.gagaframework</groupId>

+ 12 - 0
src/main/java/com/style24/front/biz/dao/TsfCouponDao.java

@@ -1,5 +1,7 @@
 package com.style24.front.biz.dao;
 
+import java.util.Collection;
+
 import com.style24.core.support.annotation.ShopDs;
 import com.style24.persistence.domain.Cart;
 import com.style24.persistence.domain.Coupon;
@@ -28,4 +30,14 @@ public interface TsfCouponDao {
 	 * @since 2021. 02. 17
 	 */
 	Coupon getSearchSerialCpnInfo(Coupon param);
+
+	/**
+	 * 마이페이지 등급쿠폰 다운가능 쿠폰 정보 조회
+	 * 
+	 * @param coupon
+	 * @return Collection<Coupon>
+	 * @author card007
+	 * @since 2021.02.25
+	 */
+	Collection<Coupon> getCustGradeCouponInfo(Coupon coupon);
 }

+ 13 - 0
src/main/java/com/style24/front/biz/dao/TsfCustomerDao.java

@@ -1,6 +1,7 @@
 package com.style24.front.biz.dao;
 
 import com.style24.core.support.annotation.ShopDs;
+import com.style24.persistence.domain.CustSnsInfo;
 import com.style24.persistence.domain.Customer;
 
 /**
@@ -47,4 +48,16 @@ public interface TsfCustomerDao {
 	 * @since 2021. 02. 22
 	 */
 	int createCustomerSns(Customer customer);
+
+	/**
+	 * 활동, 휴면 테이블 조회
+	 * @param customer - 고객정보
+	 * @return 고객정보
+	 * @author jsshin
+	 * @since 2021. 02. 24
+	 */
+	Customer getCusomterActiveAndDormant(Customer customer);
+
+
+	Customer getCusomterSnsFind(CustSnsInfo custSnsInfo);
 }

+ 1 - 3
src/main/java/com/style24/front/biz/service/TsfCartService.java

@@ -51,7 +51,7 @@ public class TsfCartService {
 	 * 세트 : goodsCd,
 	 * @param cart
 	 */
-	public String saveCartInfo(Collection<Cart> params) {
+	public void saveCartInfo(Collection<Cart> params) {
 		Cart cart = new Cart();
 
 		// 로그인 유무 확인 (로그인이 되어 있지 않으면 regNo 를 0으로 장바구니에 저장한다.)
@@ -110,8 +110,6 @@ public class TsfCartService {
 			// 세트 상품이 아닐 경우
 			saveNormalDealCartInfo(params.iterator().next());
 		}
-
-		return "SUCCESS";
 	}
 
 	@Transactional("shopTxnManager")

+ 36 - 5
src/main/java/com/style24/front/biz/service/TsfCouponService.java

@@ -126,17 +126,12 @@ public class TsfCouponService {
 		int totCurrPrice = 0;
 		int maxDcAmt = 0;
 		int buyLimitAmt = 0;
-		log.info("CHECK INFO >> {}", 1);
 		if(param != null && param.getCartSqArr().length > 0) {
-			log.info("CHECK INFO >> {}", 2);
 			Collection<Order> serialGoodsList = coreOrderService.getSerialCpnApplyGoodsList(order);
-			log.info("CHECK INFO >> {} / {}", 3, serialGoodsList.size());
 			for (int i = 0; i < param.getCartSqArr().length; i++) {
-				log.info("CHECK INFO >> {}", 4);
 				for (Order cpnInfo : serialGoodsList) {
 					if("A".equals(cpnInfo.getApplyScope()) || param.getCartSqArr()[i] == cpnInfo.getCartSq()) {
 						cpnInfo.setCurrPrice(param.getCurrPrices()[i]);
-						log.info("CHECK INFO >> {}", param.getCurrPrices()[i]);
 					}
 				}
 			}
@@ -191,4 +186,40 @@ public class TsfCouponService {
 		coreCouponDao.updateGiveRandomCoupon(custCoupon);		// 랜덤쿠폰 CUST_NO UPDATE
 		coreCouponDao.saveCouponCustPub(custCoupon);			// 랜덤쿠폰 고객 지급
 	}
+
+	/**
+	 * 마이페이지 등급쿠폰 다운 처리
+	 *
+	 * @param coupon
+	 * @return Collection<Coupon>
+	 * @author card007
+	 * @since 2021.02.25
+	 */
+	@Transactional("shopTxnManager")
+	public int createCustGradeAllCoupon(Coupon coupon) {
+		int count = 0;
+		
+		Collection<Coupon> couponList = couponDao.getCustGradeCouponInfo(coupon);
+		
+		for(Coupon tmpCoupon : couponList) {
+			int downloadCnt = tmpCoupon.getDownloadCnt();
+			for (int i = 0; i < downloadCnt; i++) {
+				CustCoupon custCoupon = new CustCoupon();
+				custCoupon.setCustNo(tmpCoupon.getCustNo());
+				custCoupon.setCpnId(tmpCoupon.getCpnId());
+				custCoupon.setAvailStdt(tmpCoupon.getAvailStdt());
+				custCoupon.setAvailEddt(tmpCoupon.getAvailEddt());
+				custCoupon.setPubReason(TscConstants.PubReason.DOWNLOAD.value());
+				custCoupon.setEndAlimSendYn(tmpCoupon.getEndAlimYn());
+				custCoupon.setRegNo(tmpCoupon.getCustNo());
+				custCoupon.setUpdNo(tmpCoupon.getCustNo());
+
+				coreCouponDao.saveCouponCustPub(custCoupon);
+
+				count++;
+			}
+		}
+		
+		return count;
+	}
 }

+ 165 - 9
src/main/java/com/style24/front/biz/service/TsfCustomerService.java

@@ -1,12 +1,16 @@
 package com.style24.front.biz.service;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.gagaframework.web.parameter.GagaMap;
 import com.gagaframework.web.security.GagaPasswordEncoder;
 import com.style24.core.biz.service.TscCustomerService;
 import com.style24.core.support.env.TscConstants;
 import com.style24.core.support.session.TscSession;
+import com.style24.core.support.util.CryptoUtils;
 import com.style24.front.support.security.TsfLoginDetails;
+import com.style24.front.support.security.session.TsfSession;
 import com.style24.persistence.domain.Coupon;
+import com.style24.persistence.domain.CustSnsInfo;
 import com.style24.persistence.domain.Customer;
 import com.style24.persistence.domain.Login;
 import com.style24.persistence.domain.Point;
@@ -47,6 +51,9 @@ public class TsfCustomerService {
 	@Autowired
 	private TsfLoginService loginService;
 
+	@Autowired
+	private ObjectMapper objectMapper;
+
 
 	/**
 	 * 고객아이디 찾기
@@ -60,9 +67,27 @@ public class TsfCustomerService {
 		TscSession.setAttribute("maskingYn","Y");
 		customer.setSiteCd(TscConstants.Site.STYLE24.value());
 		customer.encryptData(); // 데이터 암호하
+		return customerDao.getCusomterActiveAndDormant(customer);
+	}
+
+	/**
+	 * 고객정보찾기 -
+	 *
+	 * @param custNo - 고객번호
+	 * @return Customer 고객정보
+	 * @author jsshin
+	 * @since 2021. 02. 24
+	 */
+	public Customer getCustomerFindByCustNo(Integer custNo) {
+		Customer customer = new Customer();
+		customer.setCustNo(custNo);
+		customer.setCustStat(TscConstants.CustStat.ACTIVE.value());
+		customer.setSiteCd(TscConstants.Site.STYLE24.value());
+		customer.encryptData();
 		return coreCustomerService.getCustomerInfo(customer);
 	}
 
+
 	/**
 	 * 임시비밀번호 조회
 	 * @param length - 비밀번호 자릿수
@@ -122,9 +147,27 @@ public class TsfCustomerService {
 		return result > 0;
 	}
 
+	/**
+	 * 해당 휴대전화로 가입된 이력이 있는지 확인
+	 * @param cellPhnno - 휴대전화
+	 * @return boolean - 있으면 TRUE/ 없으면 FALSE
+	 * @author jsshin
+	 * @since 2021. 02. 15
+	 */
+	public boolean getCustomerFindByCellPhnnoCount(String cellPhnno) {
+		Customer customer = new Customer();
+		customer.setCellPhnno(cellPhnno);
+		customer.setHypenCellPhone(); // 010-0000-0000
+		customer.setSiteCd(TscConstants.Site.STYLE24.value());
+		customer.encryptData();
+		int result = customerDao.getCustomerInfoCount(customer);
+
+		return result > 0;
+	}
+
 	/**
 	 * 해당 CI로 가입된 이력이 있는지 확인
-	 * @param ci - ci
+	 * @param ci - 연계정보
 	 * @return boolean - 있으면 TRUE/ 없으면 FALSE
 	 * @author jsshin
 	 * @since 2021. 02. 15
@@ -141,7 +184,7 @@ public class TsfCustomerService {
 	/**
 	 * 해당 휴대폰 번호로 가입된 이력이 있는지 확인
 	 * @param cellPhnno - 휴대전화번호
-	 * @return boolean - 있으면 TRUE/ 없으면 FALSE
+	 * @return Customer - 고객정보
 	 * @author jsshin
 	 * @since 2021. 02. 15
 	 */
@@ -201,8 +244,9 @@ public class TsfCustomerService {
 	}
 
 	/**
-	 * 회원가입 처리
-	 * @param customer - 일반가입, SNS 가입
+	 * 회원가입 처리 - 일반가입
+	 * @param customer - 일반가입
+	 * @return boolean - 가입 성공 true / 실패 false
 	 * @author jsshin
 	 * @since 2021. 02. 19
 	 */
@@ -210,17 +254,50 @@ public class TsfCustomerService {
 	public boolean saveJoinCustomer(Customer customer) {
 		boolean isJoin = true;
 		// 1. validation
+		customer.setHypenCellPhone();
 		customer.encryptData();
-		if (StringUtils.isNotBlank(customer.getSnsId())) {
-			customer.setEncodedPasswd(" ");
-			customer.setCustId(customer.getSnsType()+"_"+customer.getSnsId());
+		customer.setEncodedPasswd(passwordEncoder.encode(customer.getPasswd()));
+
+		customer.setCustStat(TscConstants.CustStat.ACTIVE.value());
+		customer.setCustGb(TscConstants.CustGb.NORMAL.value());
+		customer.setCustGrade(TscConstants.CustGrade.WELCOME.value());
+
+		int custCnt = customerDao.createCustomer(customer);
+
+		if (custCnt > 0) {
+			saveJoinPostProcessing(customer);
 		} else {
-			customer.setEncodedPasswd(passwordEncoder.encode(customer.getPasswd()));
+			isJoin = false;
 		}
+
+		return isJoin;
+	}
+
+	/**
+	 * 회원가입 처리 - SNS 간편가입
+	 * @param customer - SNS 정보
+	 * @return boolean - 가입 성공 true / 실패 false
+	 * @author jsshin
+	 * @since 2021. 02. 19
+	 */
+	public boolean saveJoinCustomerSns (Customer customer) {
+		boolean isJoin = true;
+		customer.setEncodedPasswd(" ");
+		customer.setCustId(customer.getSnsType()+"_"+customer.getSnsId());
+		customer.setEncodedPasswd(passwordEncoder.encode(customer.getPasswd()));
+		customer.encryptData();
+
+		String gender = "G007_"+customer.getSexGb();
+		customer.setSexGb(gender);
+		customer.setSiteCd(TscConstants.Site.STYLE24.value());
+		customer.setFrontGb(TsfSession.getFrontGb());
+		customer.setAfLinkCd(TsfSession.getAttribute("afLinkCd"));
 		customer.setCustStat(TscConstants.CustStat.ACTIVE.value());
 		customer.setCustGb(TscConstants.CustGb.NORMAL.value());
 		customer.setCustGrade(TscConstants.CustGrade.WELCOME.value());
+
 		int custCnt = customerDao.createCustomer(customer);
+		customerDao.createCustomerSns(customer);
 
 		if (custCnt > 0) {
 			saveJoinPostProcessing(customer);
@@ -229,6 +306,7 @@ public class TsfCustomerService {
 		}
 
 		return isJoin;
+
 	}
 
 	/**
@@ -249,9 +327,87 @@ public class TsfCustomerService {
 
 	}
 
+
+	/**
+	 * Sns 정보에대한 상태 처리
+	 * @param custSnsInfo
+	 * @author jsshin
+	 * @since 2021. 02. 19
+	 */
+	@Transactional("shopTxnManager")
+	public GagaMap customerSnsProcessing (CustSnsInfo custSnsInfo) {
+		GagaMap resultMap = new GagaMap();
+		Customer custInfo;
+
+		// 1. snsId, snsType 값으로 연동되어져 있는지 확인
+		custInfo = customerDao.getCusomterSnsFind(custSnsInfo);
+		if (custInfo != null) {
+			resultMap.setString("custStat", "SUCC_CUST");
+			return resultMap;
+		}
+
+		// 2. CI(연계정보)로 가입 되어져 있는 고객이 있는지 ?
+		custInfo = getCustomerFindByCi(custSnsInfo.getCi());
+
+		if (custInfo != null) { // 2-1. 고객정보 있는경우
+			if (TscConstants.CustStat.SECEDE.value().equals(custInfo.getCustStat())) {
+				resultMap.setString("custStat", "SECEDE_CUST"); // 탈퇴 회원
+				return resultMap;
+			}
+			if (TscConstants.CustStat.DORMANT.value().equals(custInfo.getCustStat())) {
+				resultMap.setString("custStat", "DORMANT_CUST"); // 휴면 회원
+				return resultMap;
+			}
+			if (TscConstants.CustStat.ACTIVE.value().equals(custInfo.getCustStat())) {
+
+				if (StringUtils.isBlank(custSnsInfo.getCellPhnno())) {
+					resultMap.setString("custStat", "EMPTY_PHONE_CUST");
+					return resultMap;
+				}
+				custInfo.setSnsId(custSnsInfo.getSnsId());
+				custInfo.setSnsType(custSnsInfo.getSnsType());
+				customerDao.createCustomerSns(custInfo);
+				resultMap.setString("custStat", "SUCC_CUST");
+				return resultMap;
+			}
+		} else { // 2-2. 고객정보 없는 경우
+
+			if (StringUtils.isBlank(custSnsInfo.getCellPhnno())) { // 휴대전화번호가 없는 경우
+				resultMap.setString("custStat", "EMPTY_PHONE_CUST");
+				return resultMap;
+			}
+
+			boolean isFindByPhone =getCustomerFindByCellPhnnoCount(custSnsInfo.getCellPhnno().replace("-",""));
+			if (isFindByPhone) {
+				resultMap.setString("custStat", "DUP_PHONE_CUST");
+				return resultMap;
+			}
+
+			boolean isFindByEmail = getCustomerFindByEmail(custSnsInfo.getEmail());
+			if (isFindByEmail) {
+				resultMap.setString("custStat", "DUP_EMAIL_CUST"); // 이메일 중복
+				return resultMap;
+			}
+
+			Customer customer = objectMapper.convertValue(custSnsInfo, Customer.class);
+
+			boolean isJoin = saveJoinCustomerSns(customer);
+
+			if (isJoin) {
+				resultMap.setString("custStat", "SUCC_CUST");
+			} else {
+				resultMap.setString("custStat", "FAIL_CUST");
+			}
+
+		}
+
+		return resultMap;
+	}
+
+
 	/**
 	 * 로그인 처리
-	 * @param custNo - 고객번호
+	 * @param custId - 고객아이디
 	 * @param request - 요청
 	 * @author jsshin
 	 * @since 2021. 02. 18

+ 116 - 21
src/main/java/com/style24/front/biz/thirdparty/KaKaoLogin.java

@@ -2,8 +2,12 @@ package com.style24.front.biz.thirdparty;
 
 import com.gagaframework.web.parameter.GagaMap;
 import com.gagaframework.web.util.GagaFileUtil;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
 import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
+import com.google.i18n.phonenumbers.NumberParseException;
+import com.google.i18n.phonenumbers.PhoneNumberUtil;
+import com.google.i18n.phonenumbers.Phonenumber;
 import com.style24.front.support.security.session.TsfSession;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
@@ -20,6 +24,7 @@ import org.springframework.web.client.RestTemplate;
 
 import javax.annotation.PostConstruct;
 import java.net.URI;
+import java.util.Locale;
 
 
 /**
@@ -38,6 +43,8 @@ public class KaKaoLogin {
 	@Autowired
 	private RestTemplate restTemplate;
 
+	public static final String PROTOCOL = "http://";
+
 	private String callBackUrl;
 	private String restApiKey;
 	private String profiles;
@@ -66,17 +73,39 @@ public class KaKaoLogin {
 		log.info("\n--- Kakao initialization completed ----\n");
 	}
 
+	/**
+	 * 카카오 로그인 창
+	 * @param state - 콜백 시 해당 값으로 비교 및 모바일을 redirect 값이 있음
+	 * @return String - 호출 url정보
+	 * @author jsshin
+	 * @since 2021. 02. 05
+	 */
 	public String getAuthorizeUrl(String state) {
-		String apiUrl = authorizeUrl;
-		String redirectUri = GagaFileUtil.getConcatenationPath("https://" + TsfSession.getHttpServletRequest().getServerName(), callBackUrl);
-		apiUrl += "?client_id=" + restApiKey + "&redirect_uri=" + redirectUri + "&response_type=code&state=" + state;
-		log.info("api ===> {}", apiUrl);
-		return apiUrl;
+		StringBuilder apiUrlBuilder = new StringBuilder();
+		String redirectUri = GagaFileUtil.getConcatenationPath(PROTOCOL + TsfSession.getHttpServletRequest().getServerName(), callBackUrl);
+		apiUrlBuilder.append(authorizeUrl)
+				.append("?client_id=")
+				.append(restApiKey)
+				.append("&redirect_uri=")
+				.append(redirectUri)
+				.append("&response_type=code&state=")
+				.append(state);
+		log.info("apiUrlBuilder ===> {}", apiUrlBuilder.toString());
+		return apiUrlBuilder.toString();
 	}
 
+	/**
+	 * 카카오 전달 받은 코드 값으로 토근값을 받아옴(API)
+	 *
+	 * @param code - 카카오에서 전달 해준 값
+	 * @param state - 콜백 시 해당 값으로 비교 및 모바일을 redirect 값이 있음
+	 * @return GagaMap - 통신으로 받아온 정보
+	 * @author jsshin
+	 * @since 2021. 02. 05
+	 */
 	public GagaMap getAccessTocken(String code, String state) {
 		GagaMap resultMap = new GagaMap();
-		String redirectUri = GagaFileUtil.getConcatenationPath("https://" + TsfSession.getHttpServletRequest().getServerName(), callBackUrl);
+		String redirectUri = GagaFileUtil.getConcatenationPath(PROTOCOL + TsfSession.getHttpServletRequest().getServerName(), callBackUrl);
 		String requestGb = "";
 		try {
 			MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
@@ -89,7 +118,7 @@ public class KaKaoLogin {
 			// state 값에 리다이렉트 url 같이 넘겨줌
 			if (StringUtils.isNotBlank(state)) {
 				String[] stateArr = StringUtils.split(state, "!@!");
-				   requestGb = stateArr[1];
+				requestGb = stateArr[1];
 			}
 
 			// Header
@@ -106,17 +135,24 @@ public class KaKaoLogin {
 			String jsonResult = responseEntity.getBody();
 			log.info("responseEntity.getBody(): {} ", jsonResult);
 
-			JsonObject obj = new JsonParser().parse(jsonResult).getAsJsonObject();
-
-			resultMap.setString("access_token", obj.get("access_token").toString());
-			resultMap.setString("refresh_token", obj.get("refresh_token").toString());
+			Gson gson = new GsonBuilder().create();
+			resultMap = gson.fromJson(jsonResult, GagaMap.class); //access_token, refresh_token
 			resultMap.setString("requestGb", requestGb);
+
 		} catch (Exception e) {
 			log.error(e.getMessage());
 		}
 		return resultMap;
 	}
 
+	/**
+	 * 카카오 사용자 정보
+	 *
+	 * @param accessToken - 해당 값으로 사용자 정보를 가져옴
+	 * @return GagaMap - 사용자 정보
+	 * @author jsshin
+	 * @since 2021. 02. 05
+	 */
 	public GagaMap getKakaoUserInfo(String accessToken) {
 		GagaMap resultMap = new GagaMap();
 		try {
@@ -137,12 +173,34 @@ public class KaKaoLogin {
 			String jsonResult = responseEntity.getBody();
 			log.info("responseEntity.getBody(): {} ", jsonResult);
 
+			Gson gson = new GsonBuilder().create();
+
+			JsonObject obj = gson.fromJson(jsonResult, JsonObject.class);
+			GagaMap properties = gson.fromJson(obj.get("properties"), GagaMap.class);
+			GagaMap kakaoAccount = gson.fromJson(obj.get("kakao_account"), GagaMap.class);
+
+			Locale locale = Locale.KOREA;
+			String cellPhnno = getPhoneNumber(kakaoAccount.getString("phone_number"), locale.getCountry());
+			String birthYmd = kakaoAccount.getString("birthyear") + kakaoAccount.getString("birthday");
+
+			String sexGb = "";
+			if (StringUtils.isNotBlank(kakaoAccount.getString("gender"))) {
+				sexGb = kakaoAccount.getString("gender").equals("male") ? "M" : "F";
+			}
 
-			JsonObject obj = new JsonParser().parse(jsonResult).getAsJsonObject();
-			JsonObject properties = obj.get("properties").getAsJsonObject();
+			String birthSm = "";
+			if (StringUtils.isNotBlank(kakaoAccount.getString("birthday_type"))) {
+				birthSm = kakaoAccount.getString("birthday_type").equals("SOLAR") ? "S":"L";
+			}
 
-			resultMap.setString("id", obj.get("id").toString());
-			resultMap.setString("name", properties.get("nickname").toString());
+			resultMap.setString("snsId", obj.get("id").toString());
+			resultMap.setString("custNm", properties.getString("nickname"));
+			resultMap.setString("email", kakaoAccount.getString("email"));
+			resultMap.setString("ci", kakaoAccount.getString("ci"));
+			resultMap.setString("cellPhnno", cellPhnno);
+			resultMap.setString("birthYmd", birthYmd);
+			resultMap.setString("birthSm", birthSm);
+			resultMap.setString("sexGb", sexGb);
 
 		} catch (Exception e) {
 			log.error(e.getMessage());
@@ -150,6 +208,14 @@ public class KaKaoLogin {
 		return resultMap;
 	}
 
+	/**
+	 * 카카오 access_token 새로 발급
+	 *
+	 * @param refreshToken - 해당 값으로 사용자 정보를 가져옴
+	 * @return GagaMap - access_token 값을 준다.
+	 * @author jsshin
+	 * @since 2021. 02. 05
+	 */
 	public GagaMap getRefreshTocken(String refreshToken) {
 		GagaMap resultMap = new GagaMap();
 		try {
@@ -172,15 +238,22 @@ public class KaKaoLogin {
 			String jsonResult = responseEntity.getBody();
 			log.info("responseEntity.getBody(): {} ", jsonResult);
 
-			JsonObject obj = new JsonParser().parse(jsonResult).getAsJsonObject();
-			resultMap.setString("access_token", obj.get("access_token").toString());
-
+			Gson gson = new GsonBuilder().create();
+			resultMap = gson.fromJson(jsonResult, GagaMap.class); //access_token
 		} catch (Exception e) {
 			log.error(e.getMessage());
 		}
 		return resultMap;
 	}
 
+	/**
+	 * 카카오 계정 연동해제
+	 *
+	 * @param accessToken - 토근값
+	 * @return GagaMap - snsId 값이 있으면 연동해제 성공
+	 * @author jsshin
+	 * @since 2021. 02. 05
+	 */
 	public GagaMap saveUnlink(String accessToken) {
 		GagaMap resultMap = new GagaMap();
 		try {
@@ -199,12 +272,34 @@ public class KaKaoLogin {
 			String jsonResult = responseEntity.getBody();
 			log.info("responseEntity.getBody(): {} ", jsonResult);
 
-			JsonObject obj = new JsonParser().parse(jsonResult).getAsJsonObject();
-			resultMap.setString("id", obj.get("id").toString());
+			Gson gson = new GsonBuilder().create();
+			JsonObject obj =  gson.fromJson(jsonResult, JsonObject.class);
+
+			resultMap.setString("snsId", obj.get("id").toString());
 
 		} catch (Exception e) {
 			log.error(e.getMessage());
 		}
 		return resultMap;
 	}
+
+	/**
+	 * 국가번호 붙여서 넘겨온 전화번호 변호
+	 * +82) 010 1234 5678 -> 010-1234-5678
+	 * @param cellPhnno - 휴대전화번호
+	 * @param country - 국가
+	 * @return String - 010-1234-5678
+	 * @author jsshin
+	 * @since 2021. 02. 05
+	 */
+	public String getPhoneNumber(String cellPhnno, String country) throws Exception {
+		String result = "";
+		if (StringUtils.isNotBlank(cellPhnno)) {
+			PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
+			Phonenumber.PhoneNumber numberProto = phoneUtil.parse(cellPhnno, "KR");
+			result = phoneUtil.format(numberProto, PhoneNumberUtil.PhoneNumberFormat.NATIONAL);
+		}
+
+		return result;
+	}
 }

+ 28 - 11
src/main/java/com/style24/front/biz/thirdparty/NaverLogin.java

@@ -4,6 +4,8 @@ import java.net.URI;
 
 import javax.annotation.PostConstruct;
 
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
 import com.style24.front.support.security.session.TsfSession;
@@ -41,6 +43,8 @@ public class NaverLogin {
 	@Autowired
 	private RestTemplate restTemplate;
 
+	public static final String PROTOCOL = "http://";
+
 	private String callBackUrl;
 	private String clientId;
 	private String clientSecret;
@@ -71,11 +75,18 @@ public class NaverLogin {
 	}
 
 	public String getAuthorizeUrl(String state) {
-		String apiUrl = authorizeUrl;
-		String redirectUri = GagaFileUtil.getConcatenationPath("https://" + TsfSession.getHttpServletRequest().getServerName(), callBackUrl);
-		apiUrl += "?response_type=code&client_id=" + clientId + "&redirect_uri=" + redirectUri + "&state=" + state;
-		log.info("api ===> {}", apiUrl);
-		return apiUrl;
+		StringBuilder apiUrlBuilder = new StringBuilder();
+		String redirectUri = GagaFileUtil.getConcatenationPath(PROTOCOL + TsfSession.getHttpServletRequest().getServerName(), callBackUrl);
+		apiUrlBuilder.append(authorizeUrl)
+				.append("?response_type=code&client_id=")
+				.append(clientId)
+				.append("&redirect_uri=")
+				.append(redirectUri)
+				.append("&state=")
+				.append(state);
+
+		log.info("apiUrlBuilder ===> {}", apiUrlBuilder.toString());
+		return apiUrlBuilder.toString();
 	}
 
 	public GagaMap getAccessTocken(String code, String state) {
@@ -109,11 +120,13 @@ public class NaverLogin {
 			String jsonResult = responseEntity.getBody();
 			log.info("getAccessTocken responseEntity.getBody(): {} ", jsonResult);
 
-			JsonObject obj = new JsonParser().parse(jsonResult).getAsJsonObject();
+			Gson gson = new GsonBuilder().create();
+			JsonObject obj = gson.fromJson(jsonResult, JsonObject.class);
 
 			resultMap.setString("access_token", obj.get("access_token").toString());
 			resultMap.setString("refresh_token", obj.get("refresh_token").toString());
 			resultMap.setString("requestGb", requestGb);
+
 		} catch (Exception e) {
 			log.error(e.getMessage());
 		}
@@ -140,10 +153,11 @@ public class NaverLogin {
 			String jsonResult = responseEntity.getBody();
 			log.info("getNaverUserInfo responseEntity.getBody(): {} ", jsonResult);
 
-			JsonObject obj = new JsonParser().parse(jsonResult).getAsJsonObject();
-			JsonObject response = obj.get("response").getAsJsonObject();
+			Gson gson = new GsonBuilder().create();
+			JsonObject obj = gson.fromJson(jsonResult, JsonObject.class);
+			JsonObject response = gson.fromJson(obj.get("response"), JsonObject.class);
 
-			resultMap.setString("id", response.get("id").toString());
+			resultMap.setString("snsId", response.get("id").toString());
 			resultMap.setString("email", response.get("email").toString());
 
 		} catch (Exception e) {
@@ -175,7 +189,9 @@ public class NaverLogin {
 			String jsonResult = responseEntity.getBody();
 			log.info("getRefreshTocken responseEntity.getBody(): {} ", jsonResult);
 
-			JsonObject obj = new JsonParser().parse(jsonResult).getAsJsonObject();
+			Gson gson = new GsonBuilder().create();
+			JsonObject obj =  gson.fromJson(jsonResult, JsonObject.class);
+
 			resultMap.setString("access_token", obj.get("access_token").toString());
 
 		} catch (Exception e) {
@@ -208,7 +224,8 @@ public class NaverLogin {
 			String jsonResult = responseEntity.getBody();
 			log.info("saveUnlink : responseEntity.getBody(): {} ", jsonResult);
 
-			JsonObject obj = new JsonParser().parse(jsonResult).getAsJsonObject();
+			Gson gson = new GsonBuilder().create();
+			JsonObject obj =  gson.fromJson(jsonResult, JsonObject.class);
 
 			resultMap.setString("access_token", obj.get("access_token").toString());
 			resultMap.setString("result", obj.get("result").toString());

+ 1 - 1
src/main/java/com/style24/front/biz/web/TsfCartController.java

@@ -89,7 +89,7 @@ public class TsfCartController extends TsfBaseController {
 	@PostMapping("/save")
 	public String createCart(@RequestBody Collection<Cart> params) {
 		try {
-			String result = cartService.saveCartInfo(params);
+			cartService.saveCartInfo(params);
 		} catch (Exception e) {
 			e.printStackTrace();
 			return e.getMessage();

+ 33 - 31
src/main/java/com/style24/front/biz/web/TsfCustomerController.java

@@ -1,22 +1,15 @@
 package com.style24.front.biz.web;
 
 import com.gagaframework.web.parameter.GagaMap;
-import com.gagaframework.web.security.GagaPasswordEncoder;
 import com.style24.core.biz.service.TscClauseService;
 import com.style24.core.support.env.TscConstants;
 import com.style24.core.support.session.TscSession;
 import com.style24.front.biz.service.TsfKakaoService;
-import com.style24.front.biz.service.TsfLoginService;
 import com.style24.front.biz.thirdparty.NiceCertify;
-import com.style24.front.support.env.TsfConstants;
-import com.style24.front.support.security.TsfLoginDetails;
 import com.style24.front.support.security.session.TsfSession;
 import com.style24.persistence.domain.Customer;
-import com.style24.persistence.domain.Login;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.core.authority.SimpleGrantedAuthority;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -33,9 +26,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.servlet.ModelAndView;
 
 import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-import java.util.ArrayList;
-import java.util.List;
+
 
 /**
  * 고객(회원) Controller
@@ -281,11 +272,9 @@ public class TsfCustomerController extends TsfBaseController {
 			return mav;
 		}
 
-		Customer params = new Customer();
-		params.setCustNo(Integer.valueOf(custNo));
-
 		// 고객정보 찾기
-		Customer custInfo = customerService.getCustomerFindId(params);
+		Customer custInfo = customerService.getCustomerFindByCustNo(Integer.valueOf(custNo));
+
 		if (custInfo != null) {
 			mav.addObject("custId", custInfo.getCustId());
 		}
@@ -312,10 +301,9 @@ public class TsfCustomerController extends TsfBaseController {
 			throw new IllegalStateException("고객 정보가 없습니다. 다시 확인 해주세요.");
 		}
 
-		Customer params = new Customer();
-		params.setCustNo(Integer.valueOf(custNo));
 		// 고객정보 찾기
-		Customer custInfo = customerService.getCustomerFindId(params);
+		Customer custInfo = customerService.getCustomerFindByCustNo(Integer.valueOf(custNo));
+
 		if (custInfo != null) {
 			customer.setTempPasswdYn("N"); // 임시비밀번호여부
 			customer.setRegNo(custInfo.getCustNo());
@@ -325,6 +313,7 @@ public class TsfCustomerController extends TsfBaseController {
 			customerService.saveCustomerPassword(customer);
 			isSuccess = true;
 		}
+
 		result.setBoolean("isSuccess", isSuccess);
 		return result;
 	}
@@ -402,7 +391,7 @@ public class TsfCustomerController extends TsfBaseController {
 		ModelAndView mav = new ModelAndView();
 		GagaMap result = niceCertify.certifyCellPhone();
 
-		if (TscConstants.FrontGb.MOBIEL.vale().equals(TsfSession.getFrontGb())) {
+		if (TscConstants.FrontGb.MOBIEL.value().equals(TsfSession.getFrontGb())) {
 			mav.addObject("redirectUrl", redirectUrl); // 모바일만 사용
 		}
 
@@ -424,7 +413,7 @@ public class TsfCustomerController extends TsfBaseController {
 		ModelAndView mav = new ModelAndView();
 		GagaMap result = niceCertify.certifyIpin();
 
-		if (TscConstants.FrontGb.MOBIEL.vale().equals(TsfSession.getFrontGb())) {
+		if (TscConstants.FrontGb.MOBIEL.value().equals(TsfSession.getFrontGb())) {
 			mav.addObject("redirectUrl", redirectUrl); // 모바일만 사용
 		}
 
@@ -459,7 +448,7 @@ public class TsfCustomerController extends TsfBaseController {
 			authMethod = TscConstants.AuthMethod.IPIN.value();
 		}
 
-		if (TscConstants.FrontGb.MOBIEL.vale().equals(TsfSession.getFrontGb())) {
+		if (TscConstants.FrontGb.MOBIEL.value().equals(TsfSession.getFrontGb())) {
 			mav.addObject("redirectUrl", redirectUrl);
 		}
 
@@ -561,7 +550,7 @@ public class TsfCustomerController extends TsfBaseController {
 
 		GagaMap authInfo = niceCertify.getCertifyCellPhoneResultInfo(customer);
 		customer.setCi(authInfo.getString("sCi"));
-		//customer.setCellPhnno(authInfo.getString("sMobileNo"));
+		customer.setCellPhnno(authInfo.getString("sMobileNo"));
 		//customer.setCellPhnno("01025906246");
 
 		if ("N".equals(authInfo.getString("adult"))) {
@@ -581,7 +570,7 @@ public class TsfCustomerController extends TsfBaseController {
 	}
 
 	/**
-	 * 가입
+	 * 가입처리
 	 *
 	 * @param customer - 고객정보
 	 * @return GagaMap - 결과정보
@@ -612,17 +601,30 @@ public class TsfCustomerController extends TsfBaseController {
 
 		// 3.고객정보 생성 및 혜택 처리
 		boolean isJoin = customerService.saveJoinCustomer(customer);
-		// 4.알림톡 및 메일 발송
-		try {
-			if(StringUtils.isNotBlank(customer.getCellPhnno())) {
-				kakaoService.sendJoinCongrat(customer);
-			}
-		} catch (Exception e) {
-			log.error("error", e);
-		}
+
 
 		if (isJoin) {
-			customerService.getLogin(customer.getCustId(),request);
+			// 4.알림톡 발송
+			try {
+				if (StringUtils.isNotBlank(customer.getCellPhnno())) {
+					kakaoService.sendJoinCongrat(customer);
+				}
+			} catch (Exception e) {
+				log.error("error", e);
+			}
+
+			// 5. 이메일 발송
+			try {
+				if (StringUtils.isNotBlank(customer.getEmail())) {
+					// TODO : 2021.02.23 이메일 모듈 개발 필요 jsshin
+				}
+			} catch (Exception e) {
+				log.error("error", e);
+			}
+
+			// 6. 가입성공시 로그인 처리 실패시
+			customerService.getLogin(customer.getCustId(), request);
+
 		} else {
 			TsfSession.setAttribute("maskingCustId",customer.getMaskingCustId());
 		}

+ 151 - 0
src/main/java/com/style24/front/biz/web/TsfIndexController.java

@@ -1,17 +1,30 @@
 package com.style24.front.biz.web;
 
 import java.io.IOException;
+import java.math.BigInteger;
+import java.security.SecureRandom;
 
 import javax.servlet.RequestDispatcher;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.gagaframework.web.parameter.GagaMap;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.style24.core.support.env.TscConstants;
+import com.style24.front.biz.service.TsfCustomerService;
+import com.style24.front.biz.thirdparty.KaKaoLogin;
+import com.style24.front.biz.thirdparty.NaverLogin;
+import com.style24.persistence.domain.CustSnsInfo;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.env.Environment;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.HttpRequestMethodNotSupportedException;
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.servlet.ModelAndView;
 
@@ -39,6 +52,18 @@ public class TsfIndexController extends TsfBaseController {
 	@Autowired
 	private TscMessageByLocale message;
 
+	@Autowired
+	private TsfCustomerService customerService;
+
+	@Autowired
+	private KaKaoLogin kakaoLogin;
+
+	@Autowired
+	private NaverLogin naverLogin;
+
+	@Autowired
+	private ObjectMapper objectMapper;
+
 	/**
 	 * 에러 페이지
 	 * @return
@@ -131,4 +156,130 @@ public class TsfIndexController extends TsfBaseController {
 		return mav;
 	}
 
+	/**
+	 * 카카오 로그인 페이지 호출
+	 *
+	 * @return String
+	 * @author jsshin
+	 * @since 2021. 02. 23
+	 */
+	@GetMapping("/signin/kakologin")
+	public String signinKaKaoLogin(@RequestParam(value = "rememberMe", required = false) String rememberMe, @RequestParam(value = "requestGb", required = false) String requestGb) {
+
+		if (StringUtils.isNotBlank(rememberMe)) {
+			// RememberMe 세션 저장
+			TsfSession.setAttribute("rememberMe", rememberMe);
+		}
+		// CSRF 방지를 위한 상태 토큰 생성 코드
+		SecureRandom random = new SecureRandom();
+		String state = new BigInteger(130, random).toString(32);
+		state += "!@!" + requestGb;
+		TsfSession.setAttribute("state", state);
+
+		String redirectUrl = kakaoLogin.getAuthorizeUrl(state);
+
+		return "redirect:" + redirectUrl;
+	}
+
+	/**
+	 * 네이버 로그인 페이지 호출
+	 *
+	 * @return String
+	 * @author jsshin
+	 * @since 2020. 5. 25
+	 */
+	@GetMapping("/signin/naverlogin")
+	public String signinNaverLogin(@RequestParam(value = "rememberMe", required = false) String rememberMe, @RequestParam(value = "requestGb", required = false) String requestGb) {
+
+		if (StringUtils.isNotBlank(rememberMe)) {
+			// RememberMe 세션 저장
+			TsfSession.setAttribute("rememberMe", rememberMe);
+		}
+		// CSRF 방지를 위한 상태 토큰 생성 코드
+		SecureRandom random = new SecureRandom();
+		String state = new BigInteger(130, random).toString(32);
+		state += "!@!" + requestGb;
+		TsfSession.setAttribute("state", state);
+
+		String redirectUrl = naverLogin.getAuthorizeUrl(state);
+
+		return "redirect:" + redirectUrl;
+	}
+
+
+	/**
+	 * SNS 로그인
+	 *
+	 * @param session - HttpSession
+	 * @param snsType - SNS유형(NV:네이버, KK:카카오)
+	 * @return ModelAndView
+	 * @author jsshin
+	 * @since 2021. 02. 23
+	 */
+	@RequestMapping("/signin/snsLoginCallback")
+	public ModelAndView signinSnsLoginCallback(@RequestParam(value = "snsType", required = false) String snsType, HttpSession session
+			, @RequestParam(value = "code", required = false) String code, @RequestParam(value = "state", required = false) String state
+			, @RequestParam(value = "error", required = false) boolean isError) {
+
+		ModelAndView mav = new ModelAndView();
+
+		log.info("isError: {}", isError);
+
+		if (isError) {
+			Exception ex = (Exception)session.getAttribute("SPRING_SECURITY_LAST_EXCEPTION");
+			log.debug("e.getMessage(): {}", ex.getMessage());
+			mav.addObject("error", ex.getMessage());
+		}
+
+		GagaMap userInfo = new GagaMap();
+		boolean isSnsLoing = false;
+		if (StringUtils.isNotBlank(code) && TscConstants.SnsType.KAKAO.value().equals(snsType)) {
+			String sessionState = TsfSession.getAttribute("state");
+			if (sessionState.equals(state)) {
+				GagaMap tokenInfo = kakaoLogin.getAccessTocken(code, state);
+				userInfo = kakaoLogin.getKakaoUserInfo(tokenInfo.getString("access_token"));
+				userInfo.setString("accessToken", tokenInfo.getString("access_token"));
+				userInfo.setString("refreshToken", tokenInfo.getString("refresh_token"));
+				userInfo.setString("snsType", snsType);
+				userInfo.setString("requestGb", tokenInfo.getString("requestGb"));
+				isSnsLoing = true;
+			}
+		}
+
+		if (StringUtils.isNotBlank(code) && TscConstants.SnsType.NAVER.value().equals(snsType)) {
+			String sessionState = TsfSession.getAttribute("state");
+			if (sessionState.equals(state)) {
+				GagaMap tokenInfo = naverLogin.getAccessTocken(code, state);
+				userInfo = naverLogin.getNaverUserInfo(tokenInfo.getString("access_token"));
+				userInfo.setString("accessToken", tokenInfo.getString("access_token"));
+				userInfo.setString("refreshToken", tokenInfo.getString("refresh_token"));
+				userInfo.setString("snsType", snsType);
+				userInfo.setString("requestGb", tokenInfo.getString("requestGb"));
+				isSnsLoing = true;
+			}
+		}
+
+		// SNS 로그인 성공시 정보 세션 저장
+		GagaMap resultMap = new GagaMap();
+		if (isSnsLoing) {
+			CustSnsInfo custSnsInfo = objectMapper.convertValue(userInfo, CustSnsInfo.class);
+			//상태 체크
+			resultMap = customerService.customerSnsProcessing(custSnsInfo);
+
+		}
+
+		// RememberMe 값이 있고 true이면
+		if (StringUtils.isNotBlank(TsfSession.getAttribute("rememberMe")) && Boolean.valueOf(TsfSession.getAttribute("rememberMe"))) {
+			userInfo.setBoolean("rememberMe", true);
+		}
+
+		mav.addObject("resultMap", resultMap);
+		mav.addObject("snsId", userInfo.getString("snsId"));
+		mav.addObject("snsType", snsType);
+
+		mav.setViewName(super.getDeviceViewName("SnsCallBackForm"));
+
+		return mav;
+	}
+
 }

+ 136 - 2
src/main/java/com/style24/front/biz/web/TsfMypageController.java

@@ -34,6 +34,7 @@ import com.style24.front.biz.service.TsfWishlistService;
 import com.style24.front.support.controller.TsfBaseController;
 import com.style24.front.support.security.session.TsfSession;
 import com.style24.persistence.TscPageRequest;
+import com.style24.persistence.domain.Coupon;
 import com.style24.persistence.domain.Customer;
 import com.style24.persistence.domain.Order;
 
@@ -299,8 +300,6 @@ public class TsfMypageController extends TsfBaseController {
 	public ModelAndView exchangeForm(Order order) {
 		ModelAndView mav = new ModelAndView();
 		
-		log.info("order >>> {}", order);
-		
 		// 주문번호 설정
 		mav.addObject("ordNo", order.getOrdNo());
 
@@ -340,4 +339,139 @@ public class TsfMypageController extends TsfBaseController {
 		return mav;
 	}
 
+	/**
+	 * 마이페이지 등급쿠폰 다운 처리
+	 *
+	 * @return
+	 * @author card007
+	 * @since 2021. 02. 17
+	 */
+	@PostMapping("/coupon/download/all")
+	@ResponseBody
+	public GagaMap createCustGradeAllCoupon(@RequestBody Coupon coupon) {
+		GagaMap result = new GagaMap();
+
+		// 고객정보 조회
+		Customer customer = new Customer();
+		customer.setSiteCd(TscConstants.Site.STYLE24.value());
+		customer.setCustNo(coupon.getCustNo());
+		customer.setCustStat(TscConstants.CustStat.ACTIVE.value());
+		customer = coreCustomerService.getCustomerInfo(customer);
+
+		// 고객정보 설정
+		coupon.setCustGb(customer.getCustGb());
+		coupon.setCustGrade(customer.getCustGrade());
+
+		// 등급쿠폰 다운 처리
+		int count = couponService.createCustGradeAllCoupon(coupon);
+		
+		result.set("status", GagaResponseStatus.SUCCESS.getCode());
+		
+		if (count == 0) {
+			result.set("message", message.getMessage("COUPON_0002"));
+		} else {
+			result.set("message", message.getMessage("COUPON_0001", new Object[] {count}));
+		}
+
+		return result;
+	}
+
+	/**
+	 * 마이페이지 쿠폰 수량 조회
+	 *
+	 * @return
+	 * @author card007
+	 * @since 2021. 02. 25
+	 */
+	@PostMapping("/coupon/count")
+	@ResponseBody
+	public GagaMap fnReloadCouponCount(@RequestBody Order order) {
+		GagaMap result = new GagaMap();
+
+		// 쿠폰정보 조회
+		result.set("couponCnt", coreOrderService.getCouponInfo(order));
+
+		order.setExpiredSoon("Y");
+		result.set("expiredSoonCouponCnt", coreOrderService.getCouponInfo(order));
+
+		result.set("status", GagaResponseStatus.SUCCESS.getCode());
+
+		return result;
+	}
+
+	/**
+	 * 마이페이지 상태별 수량 조회
+	 *
+	 * @return
+	 * @author card007
+	 * @since 2021. 02. 25
+	 */
+	@PostMapping("/status/count")
+	@ResponseBody
+	public GagaMap fnReloadStatusCount(@RequestBody Order order) {
+		GagaMap result = new GagaMap();
+
+		// 쿠폰정보 조회
+		result.set("orderCount", orderService.getOrderStatCount(order));
+
+		result.set("status", GagaResponseStatus.SUCCESS.getCode());
+
+		return result;
+	}
+
+	/**
+	 * 마이페이지 반품신청 화면
+	 *
+	 * @param Order
+	 * @return ModelAndView
+	 * @author card007
+	 * @since 2021. 02. 25
+	 */
+	@PostMapping("/cancel/form")
+	@ResponseBody
+	public ModelAndView returnForm(Order order) {
+		ModelAndView mav = new ModelAndView();
+
+		// 주문번호 설정
+		mav.addObject("ordNo", order.getOrdNo());
+
+		// 고객번호 설정
+		int custNo = TsfSession.getInfo().getCustNo();
+		order.setCustNo(custNo);
+		mav.addObject("custNo", custNo);
+
+		// 고객정보 조회
+		Customer customer = new Customer();
+		customer.setSiteCd(TscConstants.Site.STYLE24.value());
+		customer.setCustNo(custNo);
+		customer.setCustStat(TscConstants.CustStat.ACTIVE.value());
+		customer = coreCustomerService.getCustomerInfo(customer);
+
+		mav.addObject("customerInfo", customer);
+
+
+		// 주문목록 조회
+		Collection<GagaMap> orderList = orderService.getOrderListForMypage(order);
+
+		if (orderList.size() == 0) {
+			mav.setViewName("redirect:/mypage/order/list/form");
+			return mav;
+		}
+
+		mav.addObject("orderList", orderList);
+
+		// 주문 결제정보 조회
+		mav.addObject("paymentInfo", orderService.getPaymentInfoForMypage(order));
+
+		// 주문 배송지 정보 조회
+		mav.addObject("deliveryAddrInfo", orderService.getOrderDeliveryAddrInfo(order));
+
+		// 교환 사유 목록 조회
+		mav.addObject("exchangeReason", rendererService.getCommonCodeList("G688", "Y"));
+
+		mav.setViewName(super.getDeviceViewName("/mypage/MypageReturnForm"));
+
+		return mav;
+	}
+
 }

+ 3 - 0
src/main/java/com/style24/persistence/domain/Coupon.java

@@ -21,6 +21,8 @@ public class Coupon extends TscBaseDomain {
 	private int[] currPrices;		// 상품가격 배열
 	private int cpnId;				// 쿠폰번호
 	private int custNo;				// 회원번호
+	private String custGb;			// 회원구분
+	private String custGrade;		// 회원등급
 	private int availDays;			// 쿠폰 다운로드 후 유효기간일
 	private int rdCpnId;			// 랜덤쿠폰번호
 	private int dcAmt;				// 할인적용금액
@@ -38,4 +40,5 @@ public class Coupon extends TscBaseDomain {
 	private String availYn;			// 지급 받은 쿠폰 사용 가능 유무
 	private String dcWay;			// 할인금액/율 구분
 	private String cpnDesc;			// 쿠폰설명
+	private int downloadCnt;		// 다운로드수
 }

+ 38 - 0
src/main/java/com/style24/persistence/domain/CustSnsInfo.java

@@ -0,0 +1,38 @@
+package com.style24.persistence.domain;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.style24.persistence.TscBaseDomain;
+import lombok.Data;
+
+/**
+ * 고객 Sns 정보 Domain
+ * @JsonSerialize 애노테이션을 지정해야 세션을 레디스에 저장할 수 있다.
+ * @author jsshin
+ * @since 2021. 02. 24
+ */
+@SuppressWarnings("serial")
+@Data
+@JsonSerialize
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class CustSnsInfo extends TscBaseDomain {
+
+	// 세션을 JSON 형식으로 레디스에 저장하려면 기본 생성자를 반드시 명시해야 한다
+	public CustSnsInfo (){
+
+	}
+	private String snsId;
+	private String snsType;
+	private String accessToken;
+	private String refreshToken;
+	private String custNm;
+	private String email;
+	private String ci;
+	private String cellPhnno;
+	private String birthYmd;
+	private String birthSm;
+	private String sexGb;
+	private Integer custNo;
+
+	private String requestGb;
+}

+ 58 - 0
src/main/java/com/style24/persistence/mybatis/shop/TsfCoupon.xml

@@ -55,4 +55,62 @@
 		<!-- 랜덤쿠폰은 RD_CPN_NM이 1개이나, 시리얼 쿠폰은 다수개이므로 하나의 정보만 조회 -->
 		LIMIT  1
 	</select>
+	
+	<!-- 마이페이지 등급쿠폰 다운가능 쿠폰 정보 조회 -->
+	<select id="getCustGradeCouponInfo" parameterType="Coupon" resultType="Coupon">
+		/* TsfCoupon.getCustGradeCouponInfo */
+		SELECT Z.CUST_NO
+		     , Z.CPN_ID
+		     , Z.AVAIL_STDT
+		     , Z.AVAIL_EDDT
+		     , Z.END_ALIM_YN
+		     , Z.DOWNLOAD_CNT
+		  FROM (SELECT A.*
+					 , CASE WHEN A.CNT <![CDATA[<=]]> 0 THEN 0
+							WHEN A.CNT > (A.DN_ABLE_CNT * A.ONE_PUB_QTY) THEN (A.DN_ABLE_CNT * A.ONE_PUB_QTY)
+							ELSE A.CNT
+						END AS DOWNLOAD_CNT
+				  FROM (SELECT #{custNo} AS CUST_NO
+							 , C.CPN_ID
+							 , C.CPN_NM
+							 , C.CUST_PUB_LIMIT_QTY
+							 , C.ONE_PUB_QTY
+							 , IF(C.PD_GB = 'P', C.AVAIL_STDT, NOW()) AS AVAIL_STDT
+							 , IF(C.PD_GB = 'P', C.AVAIL_EDDT, CONCAT(CURRENT_DATE + INTERVAL C.AVAIL_DAYS DAY, ' 23:59:59')) AS AVAIL_EDDT
+				             , C.END_ALIM_YN
+							 , IFNULL(CC.CPN_CNT, 0) AS DN_CNT
+				             , IF(C.CUST_PUB_LIMIT_QTY = 0 OR C.CUST_PUB_LIMIT_QTY - CC.CPN_CNT > 0, 1, 0) AS DN_ABLE_CNT
+				             , IF(C.TOT_PUB_LIMIT_QTY > 0, C.TOT_PUB_LIMIT_QTY - CC2.CPN_CNT, 99999) AS CNT
+						  FROM TB_COUPON C
+						 INNER JOIN TB_COUPON_CUST_GBN CCGB
+							ON C.CPN_ID = CCGB.CPN_ID
+						   AND CCGB.USABLE_CUST_GB IN ('G100_00', IFNULL(#{custGb}, 'G100_00'))
+						 INNER JOIN TB_COUPON_CUST_GRADE CCGR
+							ON C.CPN_ID = CCGR.CPN_ID
+						   AND CCGR.USABLE_CUST_GRADE = #{custGrade}
+						  LEFT OUTER JOIN (SELECT CPN_ID
+												, CUST_NO
+												, COUNT(*) AS CPN_CNT
+											 FROM TB_CUST_COUPON
+											GROUP BY CPN_ID, CUST_NO) CC
+							ON C.CPN_ID = CC.CPN_ID
+						   AND CC.CUST_NO = #{custNo}
+						  LEFT OUTER JOIN (SELECT CPN_ID
+												, COUNT(*) AS CPN_CNT
+											 FROM TB_CUST_COUPON
+											GROUP BY CPN_ID) CC2
+							ON C.CPN_ID = CC2.CPN_ID
+						 WHERE C.DOWN_ABL_YN = 'Y'
+						   AND NOW() BETWEEN C.DOWN_STDT AND C.DOWN_EDDT
+						   AND C.CPN_STAT = 'G232_11'  -- 진행
+						   AND CASE WHEN C.TOT_PUB_LIMIT_QTY = 0 THEN 1
+									WHEN C.TOT_PUB_LIMIT_QTY - CC2.CPN_CNT > 0 THEN 1
+									ELSE 0
+								END = 1
+						   AND IF(C.NEW_CUST_YN = 'Y', (SELECT COUNT(*) FROM TB_CUSTOMER WHERE CUST_NO = #{custNo} AND REG_DT BETWEEN C.CUST_JOIN_STDT AND C.CUST_JOIN_EDDT), 1) = 1
+						   AND IF(C.FIRST_ORD_YN = 'Y', (SELECT COUNT(*) FROM TB_ORDER WHERE CUST_NO = #{custNo} AND ORD_DT BETWEEN C.BUY_STDT AND C.BUY_EDDT), 0) = 0
+						) A
+				) Z
+		 WHERE Z.DOWNLOAD_CNT > 0
+	</select>
 </mapper>

+ 69 - 0
src/main/java/com/style24/persistence/mybatis/shop/TsfCustomer.xml

@@ -264,4 +264,73 @@
 		)
 	</insert>
 
+	<select id="getCusomterActiveAndDormant" parameterType="Customer" resultType="Customer">
+		/* TsfCustomer.getCusomterActiveAndDormant */
+		SELECT CUST_NO
+		     , CUST_ID
+		     , EMAIL
+		     , CELL_PHNNO
+		     , CUST_STAT
+		     , DATE_FORMAT(JOIN_DT, '%Y%m%d%H%i%S')   AS JOIN_DT
+		     , ''                                     AS DORMANT_DT
+		FROM   TB_CUSTOMER
+		WHERE  CUST_STAT = 'G104_10'
+		<if test="custId != null and custId !=''">
+		AND    CUST_ID = #{custId}
+		</if>
+		<if test="encodedCustNm != null and encodedCustNm != ''">
+		AND    CUST_NM = #{encodedCustNm}
+		</if>
+		<if test="encodedEmail != null and encodedEmail != ''">
+		AND    EMAIL = #{encodedEmail}
+		</if>
+		<if test="encodedBirthYmd != null and encodedBirthYmd != ''">
+		AND    BIRTH_YMD = #{encodedBirthYmd}
+		</if>
+		<if test="ci != null and ci != ''">
+		AND    CI = #{ci}
+		</if>
+		UNION ALL
+		SELECT CUST_NO
+		     , CUST_ID
+		     , EMAIL
+		     , CELL_PHNNO
+		     , CUST_STAT
+		     , ''                                      AS JOIN_DT
+		     , DATE_FORMAT(DORMANT_DT, '%Y%m%d%H%i%S') AS DORMANT_DT
+		FROM   TB_DORMANT_CUST
+		WHERE  1 = 1
+		<if test="custId != null and custId !=''">
+		AND    CUST_ID = #{custId}
+		</if>
+		<if test="encodedCustNm != null and encodedCustNm != ''">
+		AND    CUST_NM = #{encodedCustNm}
+		</if>
+		<if test="encodedEmail != null and encodedEmail != ''">
+		AND    EMAIL = #{encodedEmail}
+		</if>
+		<if test="encodedBirthYmd != null and encodedBirthYmd != ''">
+		AND    BIRTH_YMD = #{encodedBirthYmd}
+		</if>
+		<if test="ci != null and ci != ''">
+		AND    CI = #{ci}
+		</if>
+	</select>
+
+	<select id="getCusomterSnsFind" parameterType="CustSnsInfo" resultType="Customer">
+		SELECT C.CUST_NO
+		     , C.CUST_ID
+		     , C.CUST_NM
+		     , C.CELL_PHNNO
+		     , C.EMAIL
+		     , C.CUST_STAT
+		     , C.CI
+		FROM   TB_CUSTOMER C
+		LEFT JOIN
+		       TB_CUSTOMER_SNS CS
+		ON     C.CUST_NO = CS.CUST_NO
+		WHERE  CS.SNS_TYPE = #{snsType}
+		AND    CS.SNS_ID = #{snsId}
+	</select>
+
 </mapper>

+ 1 - 0
src/main/java/com/style24/persistence/mybatis/shop/TsfOrder.xml

@@ -221,6 +221,7 @@
 		     , ORD_NO
 		     , PAY_DT
 		     , PAY_MEANS
+		     , FN_GET_CODE_NM('G014', PAY_MEANS) AS PAY_MEANS_NM
 		     , PAY_AMT
 		     , PG_CPN_AMT
 		     , NPAY_PNT_AMT

+ 14 - 14
src/main/resources/config/application.yml

@@ -48,20 +48,20 @@ naver:
 
 #카카오 API
 kakao:
-#    appId: 442702
-#    appName: 아이스타일24
-#    companyName: 예스이십사
-#    nativeAppKey: 5d97db2ee36fa0e121d962b2531ae0c1
-#    restApiKey: 46d601394bd887cbada3cf00fdddef54
-#    javascriptKey: b3c9ee69171042c3637e8d714a4c8a75
-#    adminKey: 7cc33b2ef96d785c4caf3376f9dc9254
-    appId : 399207
-    appName : 구축용 테스트앱
-    companyName : 예스이십사
-    nativeAppKey : f961e612e07b47aa2d1884714518a194
-    restApiKey: b3955cef0328a09156c7e25f18552164
-    javascriptKey : 06cab652ad5d25be2190388d11a88fa4
-    adminKey : a25ca74dde640f3a63a8d8442fe35fcd
+    appId: 442702
+    appName: 아이스타일24
+    companyName: 예스이십사
+    nativeAppKey: 5d97db2ee36fa0e121d962b2531ae0c1
+    restApiKey: 46d601394bd887cbada3cf00fdddef54
+    javascriptKey: b3c9ee69171042c3637e8d714a4c8a75
+    adminKey: 7cc33b2ef96d785c4caf3376f9dc9254
+#    appId : 399207
+#    appName : 구축용 테스트앱
+#    companyName : 예스이십사
+#    nativeAppKey : f961e612e07b47aa2d1884714518a194
+#    restApiKey: b3955cef0328a09156c7e25f18552164
+#    javascriptKey : 06cab652ad5d25be2190388d11a88fa4
+#    adminKey : a25ca74dde640f3a63a8d8442fe35fcd
     addressApiRequestUrl : https://dapi.kakao.com/v2/local/search/address.json?page=1&query=
     login.callbackUrl: /signin/snsLoginCallback?snsType=KK
     tokenUrl: https://kauth.kakao.com/oauth/token

+ 4 - 0
src/main/resources/i18n/messages/message_ko_KR.properties

@@ -86,3 +86,7 @@ SABANGNET_0007=\uAD50\uD658\uC8FC\uBB38\uC774 \uC218\uC9D1\uB418\uC5C8\uC2B5\uB2
 SABANGNET_0008=\uBC18\uD488\uC8FC\uBB38\uC774 \uC218\uC9D1\uB418\uC5C8\uC2B5\uB2C8\uB2E4.(\uCD1D {0}\uAC74 \uC911 {1}\uAC74 \uC2E4\uD328 {2}\uAC74 \uC131\uACF5)
 SABANGNET_0009=\uC720\uD6A8\uC131 \uAC80\uC99D \uC2E4\uD328\uB85C \uCC98\uB9AC\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
 SABANGNET_0010=\uCD9C\uACE0\uB97C \uC704\uD574 ERP\uB85C \uC804\uC1A1\uD558\uC600\uC2B5\uB2C8\uB2E4.(\uC131\uACF5: {0}\uAC74, \uC2E4\uD328: {1}\uAC74)
+
+#\uCFE0\uD3F0
+COUPON_0001=\uCD1D {0}\uC7A5\uC758 \uCFE0\uD3F0\uC744 \uB2E4\uC6B4\uB85C\uB4DC \uD558\uC600\uC2B5\uB2C8\uB2E4.
+COUPON_0002=\uC774\uBBF8 \uB2E4\uC6B4\uB85C\uB4DC\uB97C \uC644\uB8CC \uD558\uC168\uC2B5\uB2C8\uB2E4.

+ 31 - 16
src/main/webapp/WEB-INF/views/web/SigninFormWeb.html

@@ -95,13 +95,13 @@
 							<h5 class="sr-only">간편로그인</h5>
 							<ul>
 								<li>
-									<a href="javascript:void(0)">
+									<a href="javascript:void(0)" onclick="cfnLoginKakao();">
 										<i class="ico ico_snslogin kakao"></i>
 										<span>카카오로 시작하기</span>
 									</a>
 								</li>
 								<li>
-									<a href="javascript:void(0)">
+									<a href="javascript:void(0)" onclick="cfnLoginNaver();">
 										<i class="ico ico_snslogin naver"></i>
 										<span>네이버로 시작하기</span>
 									</a>
@@ -230,23 +230,38 @@
 	let fnReloadCaptchaImage = function() {
 		$('#imgCaptcha').attr('src', '/common/captcha.do?dummy=' + new Date());
 	}
-	
-	// 카카오 로그인
-	var fnLoginKakao = function() {
-		document.location.href = _frontUrl + '/signin/kakologin';
-	};
-	
-	// 네이버 로그인
-	var fnLoginNaver = function() {
-		document.location.href = _frontUrl + '/signin/naverlogin';
+
+	// SNS 로그인 콜백함수
+	var fnSnsSigninCallback = function(userInfo) {
+		console.log('userInfo', userInfo);
+		let params = {};
+		params.snsType = userInfo.snsType;
+		params.snsJoinId = [[${snsLoginPrefix}]] + userInfo.snsId;
+		// $.post(_frontUrl + '/login'
+		// 	, $.param(params)
+		// 	, function(result) {
+		// 		fnReloadAfterLogin(result);
+		// 	}
+		// 	, "json");
 	};
-	
-	// YES24 로그인
-	var fnLoginYes24 = function() {
-		document.location.href = _frontUrl + '/signin/yes24login';
+
+	var fnReloadAfterLogin = function(result) {
+		if (result.status === 'OK') {
+			document.location.href = result.returnUrl;
+		} else if (result.status === 'EMAIL_DUP') {
+
+		} else if(result.status === 'DORMANT_CUST') {
+			cfnGoToPage(_PAGE_CUSTOMER_DORMANT);
+		} else if(result.status === 'SECEDE_CUST') {
+
+		} else {
+			//cfnGoToPage(_PAGE_CUSTOMER_JOIN_CERTIFY_SNS);
+		}
 	};
 
-	$(document).ready(function() {
+
+
+$(document).ready(function() {
 		$('#loginForm input[name=loginId]').val(gagajf.getCookie(ckLoginId));
 		if (gagajf.isNull($('#loginForm input[name=loginId]').val())) {
 			$('#loginForm input[name=loginId]').focus();

+ 48 - 0
src/main/webapp/WEB-INF/views/web/SnsCallBackFormWeb.html

@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html lang="ko"
+	xmlns:th="http://www.thymeleaf.org">
+<!--
+ *******************************************************************************
+ * @source  : SigninFormWeb.html
+ * @desc    : 로그인 Page
+ *============================================================================
+ * STYLE24
+ * Copyright(C) 2020 TSIT, All rights reserved.
+ *============================================================================
+ * VER  DATE         AUTHOR      DESCRIPTION
+ * ===  ===========  ==========  =============================================
+ * 1.0  2021.02.15   gagamel     최초 작성
+ *******************************************************************************
+ -->
+<head th:replace="~{web/common/fragments/HeadWeb :: head}"></head>
+<th:block th:replace="~{web/common/fragments/VariablesWeb :: variables}"></th:block>
+<th:block th:replace="~{web/common/fragments/ScriptsWeb :: scripts}"></th:block>
+<body>
+
+
+<script th:inline="javascript">
+/*<![CDATA[*/
+	const snsType = [[${snsType}]];
+	const snsId = [[${snsId}]];
+
+	if (snsType === 'KK') {
+		if (gagajf.isNull(snsId)){
+			mcxDialog.alertC("인증에 실패하였습니다.<br> 로그인 정보를 확인해주시기 바랍니다.", {
+				sureBtnText: "확인",
+				sureBtnClick: function() {
+					self.close();
+				}
+			});
+		} else {
+			opener.fnSnsSigninCallback(snsId);
+			self.close();
+		}
+	}
+
+
+/*]]>*/
+</script>
+
+
+</body>
+</html>

+ 891 - 917
src/main/webapp/WEB-INF/views/web/cart/cartListAjaxFormWeb.html

@@ -1,940 +1,914 @@
 <html lang="ko"
-      xmlns:th="http://www.thymeleaf.org">
+	  xmlns:th="http://www.thymeleaf.org">
 <form id="cartListForm" method="post" action="/order/noMember">
-    <input type="hidden" name="cartCpnDcAmt" id="cartCpnDcAmt" th:value="${param.cartCpnDcAmt}" />
-
-<!-- CONT-BODY -->
-<div class="od_cont">
-    <div class="sec_head" th:if="${order.shotCanYn.equals('Y')}">
-        <div class="tbl type4">
-            <table>
-                <colgroup>
-                    <col width="150">
-                    <col width="*">
-                </colgroup>
-                <tbody>
-                <tr>
-                    <th>
-                        배송방법 선택
-                    </th>
-                    <td>
-                        <div class="form_field">
-                            <div>
-                                <input type="radio" name="shotDelvYn" id="blt_ship1" value="">
-                                <label for="blt_ship1"><span><em class="tag">총알배송</em><span th:text="|${order.shotDelvDt}일 24:00 까지 도착|"></span></span></label>
-                            </div>
-                            <div>
-                                <input type="radio" name="shotDelvYn" id="blt_ship2" value="" checked="">
-                                <label for="blt_ship2"><span>총알 배송 안함</span></label>
-                            </div>
-                        </div>
-                    </td>
-                </tr>
-                </tbody>
-            </table>
-        </div>
-    </div>
-    <div class="sec_body">
-        <!-- 총알배송 -->
-        <div class="part_deliver wmsList" th:if="${wmsCartList != null and wmsCartList.size() > 0}">
-            <h3 class="subH2 mb20" th:if="${order.shotCanYn.equals('Y')}">
-                STYLE24 총알배송
-                <span class="ml10">오늘 자정까지 도착</span>
-            </h3>
-            <h3 class="subH2 mb20" th:if="${order.shotCanYn.equals('N')}">
-                STYLE24 일반배송
-            </h3>
-            <div class="tbl type2">
-                <table>
-                    <colgroup>
-                        <col width="900">
-                        <col width="*">
-                    </colgroup>
-                    <tbody>
-                    <th:block th:each="cart, status : ${wmsCartList}">
-                    <tr class="cartInfo wmsCartInfo">
-                        <input type="hidden" name="applyQtySectionYn" th:value="${cart.applyQtySectionYn}" />
-                        <input type="hidden" name="applyAmtSectionYn" th:value="${cart.applyAmtSectionYn}" />
-                        <input type="hidden" name="qtyTmtbSq" th:value="${cart.qtyTmtbSq}" />
-                        <input type="hidden" name="qtyTmtbNm" th:value="${cart.qtyTmtbNm}" />
-                        <input type="hidden" name="amtTmtbSq" th:value="${cart.amtTmtbSq}" />
-                        <input type="hidden" name="amtTmtbNm" th:value="${cart.amtTmtbNm}" />
-                        <input type="hidden" name="currPrice" th:value="${cart.currPrice}" />
-                        <input type="hidden" name="soldoutYn" th:value="${cart.soldoutYn}" />
-                        <input type="hidden" name="tmtbDcAmt" th:value="${cart.tmtbDcAmt}" />
-                        <input type="hidden" name="cartSq" th:value="${cart.cartSq}" />
-
-                        <td>
-                            <!-- 주문가능 상품 -->
-                            <div class="info_item" th:classappend="${cart.soldoutYn.equals('Y')} ? unable"> <!-- 주문불가시 class="unable" 추가 / 인풋, 버튼 disable 처리 -->
-                                <div class="form_box">
-                                    <p class="form_field">
-                                        <input th:id="|od_item_${cart.cartSq}|" name="cartSqArr" type="checkbox" th:value="${cart.cartSq}" th:checked="${cart.soldoutYn.equals('N')}" th:disabled="${cart.soldoutYn.equals('Y')}"/>
-                                        <label th:for="|od_item_${cart.cartSq}|">
-                                            <span class="sr-only">상품선택</span>
-                                        </label>
-                                    </p>
-                                </div>
-                                <div class="thumb_box">
-                                    <a href="">
-                                        <img th:src="${IMG_PATH} + '/' + ${cart.sysImgNm}" src="/" width="100%" alt="">
-                                    </a>
-                                </div>
-                                <div class="info_box">
-                                    <p class="od_name">
-                                        <a href="">
-                                            <span class="brand" th:text="${cart.brandNm}"></span>
-                                            <span th:if="${!#strings.isEmpty(cart.delvResDt)}" class="reserv_date" th:text="|${cart.delvResDt} 배송예정|"></span>
-                                            <span class="name" th:text="${cart.goodsNm}"></span>
-                                        </a>
-                                    </p>
-                                    <p class="od_opt" th:each="opt, index : ${cart.itemNmArr}">
-                                        <span class="option"><em th:text="${cart.itemNmArr[index.index]} + '_' + ${cart.optCdArr[index.index]}"></em></span>
-                                    </p>
-                                    <p class="od_opt">
-                                        <span class="count">수량:<em th:text="${cart.goodsQty}"></em>개</span>
-                                    </p>
-
-                                    <p class="od_modify">
-                                        <button type="button" class="btn_opt_pop"><span>옵션/수량변경</span></button>
-                                    </p>
-                                    <!-- 다다익선 적용 -->
-                                    <div class="od_moresale applyTmtb" th:if="${(cart.qtyTmtbSq > 0 and cart.applyQtySectionYn == 'Y') or (cart.amtTmtbSq > 0 and cart.applyAmtSectionYn == 'Y')}">
-                                        <a href="" class="btn_moresale">
-                                            <i class="ico ico_saletag"></i><span>다다익선 할인적용!</span>
-                                        </a>
-                                        <div class="li_moresale applyTmtbNm">
-                                            <ul>
-                                                <li th:if="${cart.qtyTmtbSq > 0 and cart.applyQtySectionYn == 'Y'}" th:text="${cart.qtyTmtbNm}"></li>
-                                                <li th:if="${cart.amtTmtbSq > 0 and cart.applyAmtSectionYn == 'Y'}" th:text="${cart.amtTmtbNm}"></li>
-                                            </ul>
-                                        </div>
-                                    </div>
-                                    <!-- 다다익선 미적용 -->
-                                    <div class="od_moresale notApplyTmtb" th:if="${(cart.qtyTmtbSq > 0 and cart.applyQtySectionYn == 'N') or (cart.amtTmtbSq > 0 and cart.applyAmtSectionYn == 'N')}">
-                                        <a href="" class="btn_moresale">
-                                            <i class="ico ico_saletag"></i><span>다다익선 상품보기</span>
-                                        </a>
-                                        <div class="li_moresale notApplyTmtbNm">
-                                            <ul>
-                                                <li th:if="${cart.qtyTmtbSq > 0 and cart.applyQtySectionYn == 'N'}" th:inline="text">[[${cart.qtyTmtbNm}]]<a href=''>대상 상품 보기</a></li>
-                                                <li th:if="${cart.amtTmtbSq > 0 and cart.applyAmtSectionYn == 'N'}" th:inline="text">[[${cart.amtTmtbNm}]]<a href=''>대상 상품 보기</a></li>
-                                            </ul>
-                                        </div>
-                                    </div>
-                                    <!-- 주문불가시 안내추가 -->
-                                    <div class="info_unable" th:if="${cart.soldoutYn.equals('Y')}">
-                                        해당상품은 구매가 불가능한 상품입니다. / 상품이 품절되었습니다.
-                                    </div>
-                                    <!-- //주문불가시 안내추가 -->
-                                </div>
-                                <div class="info_calc">
-                                    <p class="price" th:if="${cart.tmtbDcAmt < cart.currPrice}">
-                                        <span class="selling_price" th:text="|${#numbers.formatInteger(cart.tmtbDcAmt, 1, 'COMMA')} 원|"></span>
-                                        <del th:text="|${#numbers.formatInteger(cart.currPrice, 1, 'COMMA')} 원|"></del>
-                                    </p>
-                                    <p class="price" th:if="${cart.tmtbDcAmt == cart.currPrice}">
-                                        <span class="selling_price" th:text="|${#numbers.formatInteger(cart.currPrice, 1, 'COMMA')} 원|"></span>
-                                    </p>
-                                    <p class="point"><span th:text="${#numbers.formatInteger(cart.savePntAmt, 1, 'COMMA')}"></span>p 적립예정</p>
-                                    <p>
-                                        <button th:if="${cart.soldoutYn.equals('Y')}" type="button" class="btn btn_sm" disabled><span>구매불가</span></button>
-                                        <button th:if="${cart.soldoutYn.equals('N')}" type="button" class="btn btn_primary btn_sm"><span>즉시구매</span></button>
-                                    </p>
-                                    <p class="util">
+	<input type="hidden" name="cartCpnDcAmt" id="cartCpnDcAmt" th:value="${param.cartCpnDcAmt}" />
+
+	<!-- CONT-BODY -->
+	<div class="od_cont">
+		<div class="sec_head" th:if="${order.shotCanYn.equals('Y')}">
+			<div class="tbl type4">
+				<table>
+					<colgroup>
+						<col width="150">
+						<col width="*">
+					</colgroup>
+					<tbody>
+					<tr>
+						<th>
+							배송방법 선택
+						</th>
+						<td>
+							<div class="form_field">
+								<div>
+									<input type="radio" name="shotDelvYn" id="blt_ship1" value="">
+									<label for="blt_ship1"><span><em class="tag">총알배송</em><span th:text="|${order.shotDelvDt}일 24:00 까지 도착|"></span></span></label>
+								</div>
+								<div>
+									<input type="radio" name="shotDelvYn" id="blt_ship2" value="" checked="">
+									<label for="blt_ship2"><span>총알 배송 안함</span></label>
+								</div>
+							</div>
+						</td>
+					</tr>
+					</tbody>
+				</table>
+			</div>
+		</div>
+		<div class="sec_body">
+			<!-- 총알배송 -->
+			<div class="part_deliver wmsList" th:if="${wmsCartList != null and wmsCartList.size() > 0}">
+				<h3 class="subH2 mb20" th:if="${order.shotCanYn.equals('Y')}">
+					STYLE24 총알배송
+					<span class="ml10">오늘 자정까지 도착</span>
+				</h3>
+				<h3 class="subH2 mb20" th:if="${order.shotCanYn.equals('N')}">
+					STYLE24 일반배송
+				</h3>
+				<div class="tbl type2">
+					<table>
+						<colgroup>
+							<col width="900">
+							<col width="*">
+						</colgroup>
+						<tbody>
+						<th:block th:each="cart, status : ${wmsCartList}">
+							<tr class="cartInfo wmsCartInfo">
+								<input type="hidden" name="applyQtySectionYn" th:value="${cart.applyQtySectionYn}" />
+								<input type="hidden" name="applyAmtSectionYn" th:value="${cart.applyAmtSectionYn}" />
+								<input type="hidden" name="qtyTmtbSq" th:value="${cart.qtyTmtbSq}" />
+								<input type="hidden" name="qtyTmtbNm" th:value="${cart.qtyTmtbNm}" />
+								<input type="hidden" name="amtTmtbSq" th:value="${cart.amtTmtbSq}" />
+								<input type="hidden" name="amtTmtbNm" th:value="${cart.amtTmtbNm}" />
+								<input type="hidden" name="currPrice" th:value="${cart.currPrice}" />
+								<input type="hidden" name="soldoutYn" th:value="${cart.soldoutYn}" />
+								<input type="hidden" name="tmtbDcAmt" th:value="${cart.tmtbDcAmt}" />
+								<input type="hidden" name="cartSq" th:value="${cart.cartSq}" />
+
+								<td>
+									<!-- 주문가능 상품 -->
+									<div class="info_item" th:classappend="${cart.soldoutYn.equals('Y')} ? unable"> <!-- 주문불가시 class="unable" 추가 / 인풋, 버튼 disable 처리 -->
+										<div class="form_box">
+											<p class="form_field">
+												<input th:id="|od_item_${cart.cartSq}|" name="cartSqArr" type="checkbox" th:value="${cart.cartSq}" th:checked="${cart.soldoutYn.equals('N')}" th:disabled="${cart.soldoutYn.equals('Y')}"/>
+												<label th:for="|od_item_${cart.cartSq}|">
+													<span class="sr-only">상품선택</span>
+												</label>
+											</p>
+										</div>
+										<div class="thumb_box">
+											<a href="">
+												<img th:src="${IMG_PATH} + '/' + ${cart.sysImgNm}" src="/" width="100%" alt="">
+											</a>
+										</div>
+										<div class="info_box">
+											<p class="od_name">
+												<a href="">
+													<span class="brand" th:text="${cart.brandNm}"></span>
+													<span th:if="${!#strings.isEmpty(cart.delvResDt)}" class="reserv_date" th:text="|${cart.delvResDt} 배송예정|"></span>
+													<span class="name" th:text="${cart.goodsNm}"></span>
+												</a>
+											</p>
+											<p class="od_opt" th:each="opt, index : ${cart.itemNmArr}">
+												<span class="option"><em th:text="${cart.itemNmArr[index.index]} + '_' + ${cart.optCdArr[index.index]}"></em></span>
+											</p>
+											<p class="od_opt">
+												<span class="count">수량:<em th:text="${cart.goodsQty}"></em>개</span>
+											</p>
+
+											<p class="od_modify">
+												<button type="button" class="btn_opt_pop"><span>옵션/수량변경</span></button>
+											</p>
+											<!-- 다다익선 적용 -->
+											<div class="od_moresale applyTmtb" th:if="${(cart.qtyTmtbSq > 0 and cart.applyQtySectionYn == 'Y') or (cart.amtTmtbSq > 0 and cart.applyAmtSectionYn == 'Y')}">
+												<a href="" class="btn_moresale">
+													<i class="ico ico_saletag"></i><span>다다익선 할인적용!</span>
+												</a>
+												<div class="li_moresale applyTmtbNm">
+													<ul>
+														<li th:if="${cart.qtyTmtbSq > 0 and cart.applyQtySectionYn == 'Y'}" th:text="${cart.qtyTmtbNm}"></li>
+														<li th:if="${cart.amtTmtbSq > 0 and cart.applyAmtSectionYn == 'Y'}" th:text="${cart.amtTmtbNm}"></li>
+													</ul>
+												</div>
+											</div>
+											<!-- 다다익선 미적용 -->
+											<div class="od_moresale notApplyTmtb" th:if="${(cart.qtyTmtbSq > 0 and cart.applyQtySectionYn == 'N') or (cart.amtTmtbSq > 0 and cart.applyAmtSectionYn == 'N')}">
+												<a href="" class="btn_moresale">
+													<i class="ico ico_saletag"></i><span>다다익선 상품보기</span>
+												</a>
+												<div class="li_moresale notApplyTmtbNm">
+													<ul>
+														<li th:if="${cart.qtyTmtbSq > 0 and cart.applyQtySectionYn == 'N'}" th:inline="text">[[${cart.qtyTmtbNm}]]<a href=''>대상 상품 보기</a></li>
+														<li th:if="${cart.amtTmtbSq > 0 and cart.applyAmtSectionYn == 'N'}" th:inline="text">[[${cart.amtTmtbNm}]]<a href=''>대상 상품 보기</a></li>
+													</ul>
+												</div>
+											</div>
+											<!-- 주문불가시 안내추가 -->
+											<div class="info_unable" th:if="${cart.soldoutYn.equals('Y')}">
+												해당상품은 구매가 불가능한 상품입니다. / 상품이 품절되었습니다.
+											</div>
+											<!-- //주문불가시 안내추가 -->
+										</div>
+										<div class="info_calc">
+											<p class="price" th:if="${cart.tmtbDcAmt < cart.currPrice}">
+												<span class="selling_price" th:text="|${#numbers.formatInteger(cart.tmtbDcAmt, 1, 'COMMA')} 원|"></span>
+												<del th:text="|${#numbers.formatInteger(cart.currPrice, 1, 'COMMA')} 원|"></del>
+											</p>
+											<p class="price" th:if="${cart.tmtbDcAmt == cart.currPrice}">
+												<span class="selling_price" th:text="|${#numbers.formatInteger(cart.currPrice, 1, 'COMMA')} 원|"></span>
+											</p>
+											<p class="point"><span th:text="${#numbers.formatInteger(cart.savePntAmt, 1, 'COMMA')}"></span>p 적립예정</p>
+											<p>
+												<button th:if="${cart.soldoutYn.equals('Y')}" type="button" class="btn btn_sm" disabled><span>구매불가</span></button>
+												<button th:if="${cart.soldoutYn.equals('N')}" type="button" class="btn btn_primary btn_sm"><span>즉시구매</span></button>
+											</p>
+											<p class="util">
                                         <span>
                                             <button type="button" class="btn_favorite" th:classappend="${cart.wishCnt > 0} ? active"><span><i class="ico ico_like2"></i><em class="sr-only">관심상품 추가</em></span></button>
                                         </span>
-                                        <span>
+												<span>
                                             <button type="button" class="btn_delete" th:onclick="|deleteCart(${cart.cartSq})|"><span><i class="ico ico_trash"></i><em class="sr-only">상품삭제</em></span></button>
                                         </span>
-                                    </p>
-                                </div>
-                            </div>
-                            <!-- //주문가능 상품 -->
-                        </td>
-                        <td class="merge_row delvFeeArea" th:classappend="|delv_${cart.delvFeeCd}|" th:if="${cart.firstCompYn == 'Y'}" th:rowspan="${wmsCartList.size()}"> <!-- 같은 데이터 노출시 동일 영역끼리 병합 : 클래스명 merge_row 추가 -->
-                            <div class="info_dlvr">
-                                <span class="dlvr_fee" th:if="${cart.delvFee == 0}">배송비 무료</span>
-                                <span class="dlvr_fee" th:if="${cart.delvFee > 0}" th:text="|배송비 ${#numbers.formatInteger(cart.delvFee, 1, 'COMMA')} 원|"></span>
-                                <a href="#" target="_blank" th:if="${cart.delvFee > 0}">배송비 SAVE 상품 보기</a>
-                            </div>
-                        </td>
-                    </tr>
-                    </th:block>
-                    </tbody>
-                </table>
-            </div>
-            <div class="btn_area">
-                <button type="button" class="btn btn_default" onclick="deleteCart('WMS_SELECT')"><span>선택 삭제</span></button>
-                <button type="button" class="btn btn_default" onclick="deleteCart('WMS_ALL')"><span>전체 삭제</span></button>
-            </div>
-        </div>
-        <!-- //총알배송 -->
-
-        <!-- 업체직배송 -->
-        <div class="part_deliver delvList" th:if="${delvCartList != null and delvCartList.size() > 0}">
-            <h3 class="subH2 mb20">
-                업체직배송
-            </h3>
-            <div class="tbl type2">
-                <table>
-                    <colgroup>
-                        <col width="900">
-                        <col width="*">
-                    </colgroup>
-                    <tbody>
-                    <th:block th:each="cart, status : ${delvCartList}">
-                    <tr class="cartInfo delvCartInfo">
-                        <input type="hidden" name="applyQtySectionYn" th:value="${cart.applyQtySectionYn}" />
-                        <input type="hidden" name="applyAmtSectionYn" th:value="${cart.applyAmtSectionYn}" />
-                        <input type="hidden" name="qtyTmtbSq" th:value="${cart.qtyTmtbSq}" />
-                        <input type="hidden" name="qtyTmtbNm" th:value="${cart.qtyTmtbNm}" />
-                        <input type="hidden" name="amtTmtbSq" th:value="${cart.amtTmtbSq}" />
-                        <input type="hidden" name="amtTmtbNm" th:value="${cart.amtTmtbNm}" />
-                        <input type="hidden" name="currPrice" th:value="${cart.currPrice}" />
-                        <input type="hidden" name="soldoutYn" th:value="${cart.soldoutYn}" />
-                        <input type="hidden" name="tmtbDcAmt" th:value="${cart.tmtbDcAmt}" />
-                        <input type="hidden" name="cartSq" th:value="${cart.cartSq}" />
-
-                        <td>
-                            <div class="info_item" th:classappend="${cart.soldoutYn.equals('Y')} ? unable">
-                                <div class="form_box">
-                                    <p class="form_field">
-                                        <input th:id="|od_item_${cart.cartSq}|" name="cartSqArr" type="checkbox" th:value="${cart.cartSq}" th:checked="${cart.soldoutYn.equals('N')}" th:disabled="${cart.soldoutYn.equals('Y')}"/>
-                                        <label th:for="|od_item_${cart.cartSq}|">
-                                            <span class="sr-only">상품선택</span>
-                                        </label>
-                                    </p>
-                                </div>
-                                <div class="thumb_box">
-                                    <a href="">
-                                        <img th:src="${IMG_PATH} + '/' + ${cart.sysImgNm}" src="/" width="100%" alt="">
-                                    </a>
-                                </div>
-                                <div class="info_box">
-                                    <p class="od_name">
-                                        <a href="">
-                                            <span class="brand" th:text="${cart.brandNm}"></span>
-                                            <span class="name" th:text="${cart.goodsNm}"></span>
-                                        </a>
-                                    </p>
-                                    <p class="od_opt" th:each="opt, index : ${cart.itemNmArr}">
-                                        <span class="option"><em th:text="${cart.itemNmArr[index.index]} + '_' + ${cart.optCdArr[index.index]}"></em></span>
-                                    </p>
-                                    <p class="od_opt">
-                                        <span class="count">수량:<em th:text="${cart.goodsQty}"></em>개</span>
-                                    </p>
-                                    <p class="od_modify">
-                                        <button type="button" class="btn_opt_pop"><span>옵션/수량변경</span></button>
-                                    </p>
-                                    <!-- 다다익선 적용 -->
-                                    <div class="od_moresale applyTmtb" th:if="${(cart.qtyTmtbSq > 0 and cart.applyQtySectionYn == 'Y') or (cart.amtTmtbSq > 0 and cart.applyAmtSectionYn == 'Y')}">
-                                        <a href="" class="btn_moresale">
-                                            <i class="ico ico_saletag"></i><span>다다익선 할인적용!</span>
-                                        </a>
-                                        <div class="li_moresale applyTmtbNm">
-                                            <ul>
-                                                <li th:if="${cart.qtyTmtbSq > 0 and cart.applyQtySectionYn == 'Y'}" th:text="${cart.qtyTmtbNm}"></li>
-                                                <li th:if="${cart.amtTmtbSq > 0 and cart.applyAmtSectionYn == 'Y'}" th:text="${cart.amtTmtbNm}"></li>
-                                            </ul>
-                                        </div>
-                                    </div>
-                                    <!-- 다다익선 미적용 -->
-                                    <div class="od_moresale notApplyTmtb" th:if="${(cart.qtyTmtbSq > 0 and cart.applyQtySectionYn == 'N') or (cart.amtTmtbSq > 0 and cart.applyAmtSectionYn == 'N')}">
-                                        <a href="" class="btn_moresale">
-                                            <i class="ico ico_saletag"></i><span>다다익선 상품보기</span>
-                                        </a>
-                                        <div class="li_moresale notApplyTmtbNm">
-                                            <ul>
-                                                <li th:if="${cart.qtyTmtbSq > 0 and cart.applyQtySectionYn == 'N'}" th:text="${cart.qtyTmtbNm}"><a href="">대상 상품 보기</a></li>
-                                                <li th:if="${cart.amtTmtbSq > 0 and cart.applyAmtSectionYn == 'N'}" th:text="${cart.amtTmtbNm}"><a href="">대상 상품 보기</a></li>
-                                            </ul>
-                                        </div>
-                                    </div>
-                                    <!-- 주문불가시 안내추가 -->
-                                    <div class="info_unable" th:if="${cart.soldoutYn.equals('Y')}">
-                                        해당상품은 구매가 불가능한 상품입니다. / 상품이 품절되었습니다.
-                                    </div>
-                                    <!-- //주문불가시 안내추가 -->
-                                </div>
-                                <div class="info_calc">
-                                    <p class="price" th:if="${cart.tmtbDcAmt < cart.currPrice}">
-                                        <span class="selling_price" th:text="|${#numbers.formatInteger(cart.tmtbDcAmt, 1, 'COMMA')} 원|"></span>
-                                        <del th:text="|${#numbers.formatInteger(cart.currPrice, 1, 'COMMA')} 원|"></del>
-                                    </p>
-                                    <p class="price" th:if="${cart.tmtbDcAmt == cart.currPrice}">
-                                        <span class="selling_price" th:text="|${#numbers.formatInteger(cart.currPrice, 1, 'COMMA')} 원|"></span>
-                                    </p>
-                                    <p class="point"><span th:text="${#numbers.formatInteger(cart.savePntAmt, 1, 'COMMA')}"></span>p 적립예정</p>
-                                    <p>
-                                        <button th:if="${cart.soldoutYn.equals('Y')}" type="button" class="btn btn_sm" disabled><span>구매불가</span></button>
-                                        <button th:if="${cart.soldoutYn.equals('N')}" type="button" class="btn btn_primary btn_sm"><span>즉시구매</span></button>
-                                    </p>
-                                    <p class="util">
+											</p>
+										</div>
+									</div>
+									<!-- //주문가능 상품 -->
+								</td>
+								<td class="merge_row delvFeeArea" th:classappend="|delv_${cart.delvFeeCd}|" th:if="${cart.firstCompYn == 'Y'}" th:rowspan="${wmsCartList.size()}"> <!-- 같은 데이터 노출시 동일 영역끼리 병합 : 클래스명 merge_row 추가 -->
+									<div class="info_dlvr">
+										<span class="dlvr_fee" th:if="${cart.delvFee == 0}">배송비 무료</span>
+										<span class="dlvr_fee" th:if="${cart.delvFee > 0}" th:text="|배송비 ${#numbers.formatInteger(cart.delvFee, 1, 'COMMA')} 원|"></span>
+										<a href="#" target="_blank" th:if="${cart.delvFee > 0}">배송비 SAVE 상품 보기</a>
+									</div>
+								</td>
+							</tr>
+						</th:block>
+						</tbody>
+					</table>
+				</div>
+				<div class="btn_area">
+					<button type="button" class="btn btn_default" onclick="deleteCart('WMS_SELECT')"><span>선택 삭제</span></button>
+					<button type="button" class="btn btn_default" onclick="deleteCart('WMS_ALL')"><span>전체 삭제</span></button>
+				</div>
+			</div>
+			<!-- //총알배송 -->
+
+			<!-- 업체직배송 -->
+			<div class="part_deliver delvList" th:if="${delvCartList != null and delvCartList.size() > 0}">
+				<h3 class="subH2 mb20">
+					업체직배송
+				</h3>
+				<div class="tbl type2">
+					<table>
+						<colgroup>
+							<col width="900">
+							<col width="*">
+						</colgroup>
+						<tbody>
+						<th:block th:each="cart, status : ${delvCartList}">
+							<tr class="cartInfo delvCartInfo">
+								<input type="hidden" name="applyQtySectionYn" th:value="${cart.applyQtySectionYn}" />
+								<input type="hidden" name="applyAmtSectionYn" th:value="${cart.applyAmtSectionYn}" />
+								<input type="hidden" name="qtyTmtbSq" th:value="${cart.qtyTmtbSq}" />
+								<input type="hidden" name="qtyTmtbNm" th:value="${cart.qtyTmtbNm}" />
+								<input type="hidden" name="amtTmtbSq" th:value="${cart.amtTmtbSq}" />
+								<input type="hidden" name="amtTmtbNm" th:value="${cart.amtTmtbNm}" />
+								<input type="hidden" name="currPrice" th:value="${cart.currPrice}" />
+								<input type="hidden" name="soldoutYn" th:value="${cart.soldoutYn}" />
+								<input type="hidden" name="tmtbDcAmt" th:value="${cart.tmtbDcAmt}" />
+								<input type="hidden" name="cartSq" th:value="${cart.cartSq}" />
+
+								<td>
+									<div class="info_item" th:classappend="${cart.soldoutYn.equals('Y')} ? unable">
+										<div class="form_box">
+											<p class="form_field">
+												<input th:id="|od_item_${cart.cartSq}|" name="cartSqArr" type="checkbox" th:value="${cart.cartSq}" th:checked="${cart.soldoutYn.equals('N')}" th:disabled="${cart.soldoutYn.equals('Y')}"/>
+												<label th:for="|od_item_${cart.cartSq}|">
+													<span class="sr-only">상품선택</span>
+												</label>
+											</p>
+										</div>
+										<div class="thumb_box">
+											<a href="">
+												<img th:src="${IMG_PATH} + '/' + ${cart.sysImgNm}" src="/" width="100%" alt="">
+											</a>
+										</div>
+										<div class="info_box">
+											<p class="od_name">
+												<a href="">
+													<span class="brand" th:text="${cart.brandNm}"></span>
+													<span class="name" th:text="${cart.goodsNm}"></span>
+												</a>
+											</p>
+											<p class="od_opt" th:each="opt, index : ${cart.itemNmArr}">
+												<span class="option"><em th:text="${cart.itemNmArr[index.index]} + '_' + ${cart.optCdArr[index.index]}"></em></span>
+											</p>
+											<p class="od_opt">
+												<span class="count">수량:<em th:text="${cart.goodsQty}"></em>개</span>
+											</p>
+											<p class="od_modify">
+												<button type="button" class="btn_opt_pop"><span>옵션/수량변경</span></button>
+											</p>
+											<!-- 다다익선 적용 -->
+											<div class="od_moresale applyTmtb" th:if="${(cart.qtyTmtbSq > 0 and cart.applyQtySectionYn == 'Y') or (cart.amtTmtbSq > 0 and cart.applyAmtSectionYn == 'Y')}">
+												<a href="" class="btn_moresale">
+													<i class="ico ico_saletag"></i><span>다다익선 할인적용!</span>
+												</a>
+												<div class="li_moresale applyTmtbNm">
+													<ul>
+														<li th:if="${cart.qtyTmtbSq > 0 and cart.applyQtySectionYn == 'Y'}" th:text="${cart.qtyTmtbNm}"></li>
+														<li th:if="${cart.amtTmtbSq > 0 and cart.applyAmtSectionYn == 'Y'}" th:text="${cart.amtTmtbNm}"></li>
+													</ul>
+												</div>
+											</div>
+											<!-- 다다익선 미적용 -->
+											<div class="od_moresale notApplyTmtb" th:if="${(cart.qtyTmtbSq > 0 and cart.applyQtySectionYn == 'N') or (cart.amtTmtbSq > 0 and cart.applyAmtSectionYn == 'N')}">
+												<a href="" class="btn_moresale">
+													<i class="ico ico_saletag"></i><span>다다익선 상품보기</span>
+												</a>
+												<div class="li_moresale notApplyTmtbNm">
+													<ul>
+														<li th:if="${cart.qtyTmtbSq > 0 and cart.applyQtySectionYn == 'N'}" th:text="${cart.qtyTmtbNm}"><a href="">대상 상품 보기</a></li>
+														<li th:if="${cart.amtTmtbSq > 0 and cart.applyAmtSectionYn == 'N'}" th:text="${cart.amtTmtbNm}"><a href="">대상 상품 보기</a></li>
+													</ul>
+												</div>
+											</div>
+											<!-- 주문불가시 안내추가 -->
+											<div class="info_unable" th:if="${cart.soldoutYn.equals('Y')}">
+												해당상품은 구매가 불가능한 상품입니다. / 상품이 품절되었습니다.
+											</div>
+											<!-- //주문불가시 안내추가 -->
+										</div>
+										<div class="info_calc">
+											<p class="price" th:if="${cart.tmtbDcAmt < cart.currPrice}">
+												<span class="selling_price" th:text="|${#numbers.formatInteger(cart.tmtbDcAmt, 1, 'COMMA')} 원|"></span>
+												<del th:text="|${#numbers.formatInteger(cart.currPrice, 1, 'COMMA')} 원|"></del>
+											</p>
+											<p class="price" th:if="${cart.tmtbDcAmt == cart.currPrice}">
+												<span class="selling_price" th:text="|${#numbers.formatInteger(cart.currPrice, 1, 'COMMA')} 원|"></span>
+											</p>
+											<p class="point"><span th:text="${#numbers.formatInteger(cart.savePntAmt, 1, 'COMMA')}"></span>p 적립예정</p>
+											<p>
+												<button th:if="${cart.soldoutYn.equals('Y')}" type="button" class="btn btn_sm" disabled><span>구매불가</span></button>
+												<button th:if="${cart.soldoutYn.equals('N')}" type="button" class="btn btn_primary btn_sm"><span>즉시구매</span></button>
+											</p>
+											<p class="util">
                                         <span>
                                             <button type="button" class="btn_favorite"><span><i class="ico ico_like2"></i><em class="sr-only">관심상품 추가</em></span></button>
                                         </span>
-                                        <span>
+												<span>
                                             <button type="button" class="btn_delete" th:onclick="|deleteCart(${cart.cartSq})|"><span><i class="ico ico_trash"></i><em class="sr-only">상품삭제</em></span></button>
                                         </span>
-                                    </p>
-                                </div>
-                            </div>
-                        </td>
-                        <td class="merge_row delvFeeArea" th:classappend="|delv_${cart.delvFeeCd}|" th:if="${cart.firstCompYn == 'Y'}" th:rowspan="${cart.compCnt}"> <!-- 같은 데이터 노출시 동일 영역끼리 병합 : 클래스명 merge_row 추가 -->
-                            <div class="info_dlvr">
-                                <span class="dlvr_fee" th:if="${cart.delvFee == 0}">배송비 무료</span>
-                                <span class="dlvr_fee" th:if="${cart.delvFee > 0}" th:text="|배송비 ${#numbers.formatInteger(cart.delvFee, 1, 'COMMA')} 원|"></span>
-                                <span class="dlvr_shop" th:text="|${cart.supplyCompNm} 업체직배송|"></span>
-                                <a href="#" target="_blank" th:if="${cart.delvFee > 0}">배송비 SAVE 상품 보기</a>
-                            </div>
-                        </td>
-                    </tr>
-                    </th:block>
-                    </tbody>
-                </table>
-            </div>
-            <div class="btn_area">
-                <button type="button" class="btn btn_default" onclick="deleteCart('DELV_SELECT')"><span>선택 삭제</span></button>
-                <button type="button" class="btn btn_default" onclick="deleteCart('DELV_ALL')"><span>전체 삭제</span></button>
-            </div>
-        </div>
-        <!-- //업체직배송 -->
-    </div>
-</div>
-<div class="od_side">
-    <div class="area_order">
-        <div class="tit_box">
-            <h3>결제 정보</h3>
-            <span>
+											</p>
+										</div>
+									</div>
+								</td>
+								<td class="merge_row delvFeeArea" th:classappend="|delv_${cart.delvFeeCd}|" th:if="${cart.firstCompYn == 'Y'}" th:rowspan="${cart.compCnt}"> <!-- 같은 데이터 노출시 동일 영역끼리 병합 : 클래스명 merge_row 추가 -->
+									<div class="info_dlvr">
+										<span class="dlvr_fee" th:if="${cart.delvFee == 0}">배송비 무료</span>
+										<span class="dlvr_fee" th:if="${cart.delvFee > 0}" th:text="|배송비 ${#numbers.formatInteger(cart.delvFee, 1, 'COMMA')} 원|"></span>
+										<span class="dlvr_shop" th:text="|${cart.supplyCompNm} 업체직배송|"></span>
+										<a href="#" target="_blank" th:if="${cart.delvFee > 0}">배송비 SAVE 상품 보기</a>
+									</div>
+								</td>
+							</tr>
+						</th:block>
+						</tbody>
+					</table>
+				</div>
+				<div class="btn_area">
+					<button type="button" class="btn btn_default" onclick="deleteCart('DELV_SELECT')"><span>선택 삭제</span></button>
+					<button type="button" class="btn btn_default" onclick="deleteCart('DELV_ALL')"><span>전체 삭제</span></button>
+				</div>
+			</div>
+			<!-- //업체직배송 -->
+		</div>
+	</div>
+	<div class="od_side">
+		<div class="area_order">
+			<div class="tit_box">
+				<h3>결제 정보</h3>
+				<span>
                 <em class="number" th:text="${order.totCartCnt}"></em>개의 상품
             </span>
-        </div>
-        <div class="od_amount_box">
-            <dl>
-                <div>
-                    <dt>상품금액</dt>
-                    <dd><em class="sumCurrPrice" th:text="${#numbers.formatInteger(order.sumOrdAmt, 1, 'COMMA')}"></em> 원</dd>
-                </div>
-                <div>
-                    <dt>배송비</dt>
-                    <dd><em class="totDelvFee" th:text="${#numbers.formatInteger(order.totDelvFee, 1, 'COMMA')}"></em> 원</dd>
-                </div>
-                <div>
-                    <dt>할인금액</dt>
-                    <dd><span class="disc_amount"><em class="totDcAmt" id="totDcAmt" th:text="${#numbers.formatInteger(order.totDcAmt, 1, 'COMMA')}"></em> 원</span></dd>
-                </div>
-            </dl>
-        </div>
-        <div class="totalprice_box">
-            <dl>
-                <dt>총 결제 예정 금액</dt>
-                <dd data-weight="price" data-font="lato"><span class="sumRealPayAmt" id="sumRealPayAmt" th:text="${#numbers.formatInteger(order.sumRealPayAmt + order.totDelvFee, 1, 'COMMA')}"></span> 원</dd>
-            </dl>
-        </div>
-        <div class="btn_box">
-            <button class="btn btn_primary btn_block btn_md"><span>주문하기</span></button>
-        </div>
-    </div>
-    <div class="area_salecoupon">
-        <h4>할인코드 입력</h4>
-        <div class="form_field">
-            <div class="input_wrap form_full">
-                <label class="input_label sr-only">할인코드입력</label>
-                <input type="text" id="serialCpnNm" class="form_control" placeholder="할인코드를 입력해주세요.">
-            </div>
-            <button type="button" class="btn btn_dark btn_default" onclick="serialCpnApply()"><span>적용</span></button>
-        </div>
-        <div class="coupon_box">
-            <div class="coupon">
-                <div>
-                    <p class="cp_name"></p>
-                    <p class="cp_cont">
-                        <!--<span><em>12,399,900</em>원</span>
-                        <span><em>40%</em></span>-->
-                        <span class="cp_dc_val"></span>
-                    </p>
-                    <p class="cp_condition">
-                        <!--500,000원 이상 구매 시 최대 50,000원 할인
-                        <span><em class="tag">99장 보유</em></span>-->
-                    </p>
-                </div>
-                <p class="cp_date">
-                    <span class="availStdt"></span>&nbsp;~&nbsp;<span class="availEddt"></span>
-                </p>
-                <button type="button" class="btn_close_code" onClick="cancelCartCpn()">
+			</div>
+			<div class="od_amount_box">
+				<dl>
+					<div>
+						<dt>상품금액</dt>
+						<dd><em class="sumCurrPrice" th:text="${#numbers.formatInteger(order.sumOrdAmt, 1, 'COMMA')}"></em> 원</dd>
+					</div>
+					<div>
+						<dt>배송비</dt>
+						<dd><em class="totDelvFee" th:text="${#numbers.formatInteger(order.totDelvFee, 1, 'COMMA')}"></em> 원</dd>
+					</div>
+					<div>
+						<dt>할인금액</dt>
+						<dd><span class="disc_amount"><em class="totDcAmt" id="totDcAmt" th:text="${#numbers.formatInteger(order.totDcAmt, 1, 'COMMA')}"></em> 원</span></dd>
+					</div>
+				</dl>
+			</div>
+			<div class="totalprice_box">
+				<dl>
+					<dt>총 결제 예정 금액</dt>
+					<dd data-weight="price" data-font="lato"><span class="sumRealPayAmt" id="sumRealPayAmt" th:text="${#numbers.formatInteger(order.sumRealPayAmt + order.totDelvFee, 1, 'COMMA')}"></span> 원</dd>
+				</dl>
+			</div>
+			<div class="btn_box">
+				<button class="btn btn_primary btn_block btn_md"><span>주문하기</span></button>
+			</div>
+		</div>
+		<div class="area_salecoupon">
+			<h4>할인코드 입력</h4>
+			<div class="form_field">
+				<div class="input_wrap form_full">
+					<label class="input_label sr-only">할인코드입력</label>
+					<input type="text" id="serialCpnNm" class="form_control" placeholder="할인코드를 입력해주세요.">
+				</div>
+				<button type="button" class="btn btn_dark btn_default" onclick="serialCpnApply()"><span>적용</span></button>
+			</div>
+			<div class="coupon_box">
+				<div class="coupon">
+					<div>
+						<p class="cp_name"></p>
+						<p class="cp_cont">
+							<!--<span><em>12,399,900</em>원</span>
+							<span><em>40%</em></span>-->
+							<span class="cp_dc_val"></span>
+						</p>
+						<p class="cp_condition">
+							<!--500,000원 이상 구매 시 최대 50,000원 할인
+							<span><em class="tag">99장 보유</em></span>-->
+						</p>
+					</div>
+					<p class="cp_date">
+						<span class="availStdt"></span>&nbsp;~&nbsp;<span class="availEddt"></span>
+					</p>
+					<button type="button" class="btn_close_code" onClick="cancelCartCpn()">
                     <span>
                         <i class="ico ico_close1"></i>
                         <em class="sr-only">닫기</em>
                     </span>
-                </button>
-            </div>
-            <div class="info_coupon">
-                <button type="button" id="btn_cpinfo_pop">
-                    <span>쿠폰 사용안내</span>
-                </button>
-            </div>
-        </div>
-    </div>
-    <div class="area_saleitem">
-
-    </div>
-</div>
-<div class="clear"></div>
-<!-- // CONT-BODY -->
+					</button>
+				</div>
+				<div class="info_coupon">
+					<button type="button" id="btn_cpinfo_pop">
+						<span>쿠폰 사용안내</span>
+					</button>
+				</div>
+			</div>
+		</div>
+		<div class="area_saleitem">
+
+		</div>
+	</div>
+	<div class="clear"></div>
+	<!-- // CONT-BODY -->
 </form>
 
 <script th:inline="javascript">
-    let sumRealPayAmt = [[${order.sumRealPayAmt + order.totDelvFee}]];
-    let totDcAmt = [[${order.totDcAmt}]];
-
-    function NotApplyTmtbCartList() {
-        let tmtbSq = 0;
-        let tmtbNm = "";
-        let goodsList = {
-            brandNm : "",
-            goodsNm : "",
-            currPrice : 0,
-            imgPath : ""
-        }
-    }
-
-    $(document).ready(function() {
-        let compsList = [];
-
-        let temp = new Object;
-        temp.goodsCd = "STYS000000016";
-        temp.itemCd = '14373757';
-        temp.optCd = "핑크120";
-        temp.goodsQty = 1;
-        temp.goodsType = "G056_S";
-        temp.cartGb = "C";
-        temp.afLinkCd = "afLinkCd";
-        temp.ithrCd = "G027_ZZZ";
-        temp.contentsLoc = "G028_YYY";
-        temp.planDtlSq = "123";
-        compsList.push(temp);
-
-        let temp2 = new Object;
-        temp2.goodsCd = "STYS000000016";
-        temp2.itemCd = '14373758';
-        temp2.optCd = "블랙100";
-        temp2.goodsQty = 1;
-        temp2.goodsType = "G056_S";
-        temp2.cartGb = "C";
-        temp2.afLinkCd = "afLinkCd";
-        temp2.ithrCd = "G027_ZZZ";
-        temp2.contentsLoc = "G028_YYY";
-        temp2.planDtlSq = "123";
-        compsList.push(temp2);
-
-        // cfnAddCart(compsList)
-
-        $("#cartListForm .area_salecoupon .coupon_box").hide();
-        /* TODO 로그인 안했으면 .area_salecoupon (할인코드 입력 부 및 쿠폰정보영역) hide 시킬것 */
-        let loginInfo = [[${loginInfo}]];
-        if(!loginInfo || loginInfo.custNo == null || loginInfo.custNo == 0) {
-            $("#cartListForm .area_salecoupon").hide();
-        }
-
-        // 다다익선 할인 대상(미적용) 리스트
-        notApplyTmtbAreaList();
-    });
-
-    function notApplyTmtbAreaList() {
-        let notApplyQtyTmtbList = new Array();
-        let notApplyAmtTmtbList = new Array();
-
-        // 수량 다다익선 조회
-        $("#cartListForm input[name=qtyTmtbSq]").each(function (index) {
-            if($(this).val() != "0" && $(this).parent().find("input[name=applyQtySectionYn]").val() == "N") {
-                let obj = new Object();
-                obj.tmtbSq = $(this).val();
-                obj.tmtbNm = $(this).parent().find("input[name=qtyTmtbNm]").val();
-                obj.currPrice = $(this).parent().find("input[name=currPrice]").val();
-                obj.goodsNm = $(this).parent().find(".info_box").find(".name").text();
-                obj.brandNm = $(this).parent().find(".info_box").find(".brand").text();
-                obj.imgPath = $(this).parent().find(".info_item").find(".thumb_box img").attr("src");
-
-                notApplyQtyTmtbList.push(obj);
-            }
-
-            if($(this).parent().find("input[name=applyAmtSectionYn]").val() == "N") {       // 다다익선 금액은 기본상품만 가져오면됨 (N은 기본상품에 걸려있음)
-                let obj = new Object();
-                obj.tmtbSq = $(this).parent().find("input[name=amtTmtbSq]").val();
-                obj.tmtbNm = $(this).parent().find("input[name=amtTmtbNm]").val();
-
-                notApplyAmtTmtbList.push(obj);
-            }
-        });
-
-        // 수량 다다익선 정렬
-        var t = new Object();
-        for (let i = 0; i < notApplyQtyTmtbList.length; i++) {
-            for (let j = 0; j < notApplyQtyTmtbList.length - i - 1; j++) {
-                if (notApplyQtyTmtbList[j].tmtbSq > notApplyQtyTmtbList[j + 1].tmtbSq) {
-                    t = notApplyQtyTmtbList[j];
-                    notApplyQtyTmtbList[j] = notApplyQtyTmtbList[j + 1];
-                    notApplyQtyTmtbList[j + 1] = t;
-                }
-            }
-        }
-
-        fnCreateNotApplyTmtbAreaList(notApplyQtyTmtbList, notApplyAmtTmtbList);
-    }
-
-    function fnCreateNotApplyTmtbAreaList(notApplyQtyTmtbList, notApplyAmtTmtbList) {
-        // 정렬 후 같은 다다익선 상품은 한 배열로 묶음
-        let tmtbQtyList = new Array();
-
-        for (let i = 0; i < notApplyQtyTmtbList.length; i++) {
-            let goods = notApplyQtyTmtbList[i];
-            let tmtbInfo = new Object();
-            let chk = false;
-            for (let j = 0; j < tmtbQtyList.length; j++) {
-                let tmtb = tmtbQtyList[j];
-                if (goods.tmtbSq == tmtb.tmtbSq) {
-                    tmtbInfo = tmtbQtyList[j];
-                    chk = true;
-                }
-            }
-
-            // 현재 상품 정보
-            let goodsInfo = new Object();
-            goodsInfo.brandNm = goods.brandNm;
-            goodsInfo.goodsNm = goods.goodsNm;
-            goodsInfo.imgPath = goods.imgPath;
-            goodsInfo.currPrice = goods.currPrice;
-
-            // 현재 상품 정보 다다익선 정보에 세팅
-            if (chk) {
-                tmtbInfo.goodsList.push(goodsInfo);
-            } else {
-                let obj = new Object();
-                obj.tmtbSq = goods.tmtbSq;
-                obj.tmtbNm = goods.tmtbNm;
-                obj.goodsList = new Array();
-                obj.goodsList.push(goodsInfo);
-                tmtbQtyList.push(obj);
-            }
-        }
-
-        // 수량 다다익선 HTML 작성
-        let tmtbHtml = "";
-        for(let i = 0 ; i < tmtbQtyList.length ; i++) {
-            let tmtb = tmtbQtyList[i];
-            tmtbHtml += '<div class="more_sale qtyNotApplyTmtbList">';
-            for(let j = 0 ; j < tmtb.goodsList.length ; j++) {
-                let goods = tmtb.goodsList[j];
-                tmtbHtml += '<div class="item_gd">\n' +
-                        '                <figure>\n' +
-                        '                    <a href="">\n' +
-                        '                        <span class="thumb"><img src="';
-                tmtbHtml += goods.imgPath;
-                tmtbHtml += '" alt=""></span>\n' +
-                        '                    </a>\n' +
-                        '                    <figcaption>\n' +
-                        '                        <a href="">\n' +
-                        '                            <div class="brand">';
-                tmtbHtml += goods.brandNm;
-                tmtbHtml += '</div>\n' +
-                        '                            <div class="name">';
-                tmtbHtml += goods.goodsNm;
-                tmtbHtml += '</div>\n' +
-                        '                            <div class="price">\n' +
-                        '                                <span class="selling_price">';
-                tmtbHtml += Number(goods.currPrice).toLocaleString();
-                tmtbHtml += '</span>\n' +
-                        '                            </div>\n' +
-                        '                        </a>\n' +
-                        '                    </figcaption>\n' +
-                        '                </figure>\n' +
-                        '            </div>';
-            }
-
-            tmtbHtml += '<div class="txt">\n' +
-                    '                <a href="">\n' +
-                    '                    <i class="ico ico_saletag"></i>\n' +
-                    '                    <input type="hidden" name="tmtbSq" value="' + tmtb.tmtbSq + '" />' +
-                    '                    <span>\n';
-            tmtbHtml += tmtb.tmtbNm;
-            tmtbHtml += '</span>\n' +
-                    '                </a>\n' +
-                    '            </div>\n' +
-                    '        </div>';
-        }
-
-        // 금액 다다익선 정보 HTML 작성
-        for(let i = 0 ; i < notApplyAmtTmtbList.length ; i++) {
-            if (notApplyAmtTmtbList[i].tmtbSq != 0) {
-                let tmtb = notApplyAmtTmtbList[i];
-                tmtbHtml += '<div class="more_sale amtNotApplyTmtbList">\n' +
-                        '            <div class="txt">\n' +
-                        '                <a href="">\n' +
-                        '                    <i class="ico ico_saletag"></i>\n' +
-                        '                    <input type="hidden" name="tmtbSq" value="' + tmtb.tmtbSq + '" />' +
-                        '                    <span>';
-                tmtbHtml += tmtb.tmtbNm;
-                tmtbHtml += '</span>\n' +
-                        '                </a>\n' +
-                        '            </div>\n' +
-                        '        </div>';
-            }
-        }
-
-        if(tmtbHtml != "") {
-            tmtbHtml = "<h4>다다익선 할인 대상이 있습니다.</h4>" + tmtbHtml;
-        }
-
-        $(".area_saleitem").html(tmtbHtml);
-    }
-
-    function cancelCartCpn() {
-        $("#cartListForm #sumRealPayAmt").text(Number(sumRealPayAmt).toLocaleString());
-        $("#cartListForm #totDcAmt").text(Number(totDcAmt).toLocaleString());
-        $("#cartListForm .area_salecoupon .coupon_box").hide();
-    }
-
-    function serialCpnApply() {
-        let cartArr = [];
-        let currPrices = [];
-        $("#cartListForm input[name=cartSqArr]:checked").each(function(index, item) {
-            cartArr.push($(this).val());
-            currPrices.push($(this).parents(".cartInfo").find("input[name=tmtbDcAmt]").val());
-        });
-
-        let data = {
-            rdCpnNm : $("#cartListForm #serialCpnNm").val(),
-            cartSqArr : cartArr,
-            currPrices : currPrices
-        }
-
-        let jsonData = JSON.stringify(data);
-
-        $.ajax( {
-            type: "POST",
-            url : '/cart/list/serialCpnApply',
-            contentType: 'application/json',
-            dataType : 'json',
-            data : jsonData,
-            success : function(result) {
-                $("#cartListForm .area_salecoupon .coupon_box").show();
-
-                // 합계 금액
-                $("#cartListForm #sumRealPayAmt").text(Number(sumRealPayAmt - result.serialCpnInfo.dcAmt).toLocaleString());
-                $("#cartListForm #totDcAmt").text(Number(totDcAmt - result.serialCpnInfo.dcAmt).toLocaleString());
-
-                // 쿠폰 정보
-                $("#cartListForm .area_salecoupon .cp_name").text(result.serialCpnInfo.cpnNm);
-                $("#cartListForm .area_salecoupon .cp_condition").html(result.serialCpnInfo.cpnDesc + "<span><em class='tag'>1장 보유</em></span>");
-                $("#cartListForm .area_salecoupon .availStdt").text(result.serialCpnInfo.availStdt);
-                $("#cartListForm .area_salecoupon .availEddt").text(result.serialCpnInfo.availEddt);
-                if(result.serialCpnInfo.dcWay == "G240_10") {
-                    $("#cartListForm .area_salecoupon .cp_dc_val").html( "<em>" + Number(result.serialCpnInfo.dcVal).toLocaleString() + "</em> 원");
-                } else if (result.serialCpnInfo.dcWay == "G240_11") {
-                    $("#cartListForm .area_salecoupon .cp_dc_val").html( "<em>" + result.serialCpnInfo.dcVal + "%</em>");
-                }
-            }
-        });
-    };
-
-    //다다익선 적용내역 보기
-    $(document).on('click','.shopping_bag .part_deliver .btn_moresale',function(e){
-        $(this).toggleClass('active');
-        $(this).parents('.od_moresale').find('.li_moresale').toggle();
-        return false;
-    });
-
-    //관심상품 등록
-    $(document).on('click','.shopping_bag .part_deliver .btn_favorite',function(e){
-        $(this).toggleClass('active');
-        return false;
-    });
-
-    function deleteCart(gbn) {
-        let cartArr = [];
-        if(gbn == "WMS_SELECT") {
-            $("#cartListForm .wmsList input[name=cartSqArr]:checked").each(function () {
-                cartArr.push($(this).val());
-            });
-
-            if(!confirm("총 " + cartArr.length + "개의 상품을 삭제합니다.")) {
-                return false;
-            }
-        } else if(gbn == "DELV_SELECT") {
-            $("#cartListForm .delvList input[name=cartSqArr]:checked").each(function () {
-                cartArr.push($(this).val());
-            });
-
-            if(!confirm("총 " + cartArr.length + "개의 상품을 삭제합니다.")) {
-                return false;
-            }
-        } else if(gbn == "WMS_ALL") {
-            $("#cartListForm .wmsList input[name=cartSqArr]").each(function() {
-                cartArr.push($(this).val());
-            });
-
-            if(!confirm("총알배송상품을 전부 삭제하시겠습니까?")) {
-                return false;
-            }
-        } else if(gbn == "DELV_ALL") {
-            $("#cartListForm .delvList input[name=cartSqArr]").each(function() {
-                cartArr.push($(this).val());
-            });
-
-            if(!confirm("업체직배송 상품을 전부 삭제하시겠습니까?")) {
-                return false;
-            }
-        } else {
-            cartArr.push(gbn);
-        }
-
-        if(cartArr.length < 1) {
-            alert("삭제하실 상품을 선택해 주세요.");
-            return false;
-        }
-
-        let data = {
-            cartSqArr : cartArr
-        }
-
-        let jsonData = JSON.stringify(data);
-
-        $.ajax( {
-            type: "POST",
-            url : '/cart/deleteCart',
-            contentType: 'application/json',
-            dataType : 'json',
-            data : jsonData,
-            success : function(result) {
-                alert("삭제 되었습니다.");
-                getCartList();
-            }
-        });
-    }
-
-    //쿠폰사용안내 팝업열기
-    $(document).on('click','#btn_cpinfo_pop',function(e){
-        $("#cpinfoPop").modal("show");
-        return false;
-    });
-
-    $("input[name=cartSqArr]").on("change", function(e) {
-        let cartArr = [];
-
-        // 선택된 장바구니 번호
-        $("#cartListForm input[name=cartSqArr]:checked").each(function () {
-            cartArr.push($(this).val());
-        });
-
-        // 선택된 장바구니 정보 가공
-        let data = {    cartSqArr : cartArr }
-        let jsonData = JSON.stringify(data);
-
-        $.ajax( {
-            type: "POST",
-            url : '/cart/change/goods/list',
-            contentType: 'application/json',
-            dataType : 'json',
-            data : jsonData,
-            success : function(result) {
-                fnChangeCartListInfo(result);
-            }
-        });
-    });
-
-    function fnChangeCartListInfo(order) {
-        let wmsList = order.wmsCartList;
-        let delvList = order.delvCartList;
-        let cartList = new Array();
-
-        // 다다익선 정보 숨김
-        $("#cartListForm .applyTmtb").hide();
-        $("#cartListForm .notApplyTmtb").hide();
-
-        // 장바구니 각 상품 가격 정보 할인 전으로 변경
-        $("#cartListForm .cartInfo input[name=cartSq]").each(function() {
-            if($(this).parent().find(".info_calc .price > del").text() != "") {
-                $(this).parent().find(".info_calc .selling_price").text($(this).parent().find(".info_calc .price > del").text());
-                $(this).parent().find(".info_calc .price > del").remove();
-            }
-        });
-        $("#cartListForm").find(".delvFeeArea").html("<div class='info_dlvr'><span class='dlvr_fee'>배송비 무료</span></div>");
-
-        for(let i = 0 ; i < wmsList.length ; i++) {
-            cartList.push(wmsList[i]);
-            $("#cartListForm .wmsCartInfo input[name=cartSq]").each(function() {
-                if(wmsList[i].cartSq == $(this).val()) {
-                    let wms = wmsList[i];
-                    // $(this).parent().find(".thumb_box img").attr("src", result.imgPath1 + "/" + wms.sysImgNm);
-                    $(this).parent().find(".od_moresale .applyTmtbNm > ul").html("");
-                    $(this).parent().find(".od_moresale .notApplyTmtbNm > ul").html("");
-
-                    // 다다익선 적용 정보 생성성
-                    if(wms.qtyTmtbSq > 0 && wms.applyQtySectionYn == "Y") {
-                        $(this).parent().find(".applyTmtb .applyTmtbNm > ul").append("<li>" + wms.qtyTmtbNm + "</li>");
-                        $(this).parent().find(".applyTmtb").show();
-                    }
-                    if(wms.amtTmtbSq > 0 && wms.applyAmtSectionYn == "Y") {
-                        $(this).parent().find(".applyTmtb .applyTmtbNm > ul").append("<li>" + wms.amtTmtbNm + "</li>");
-                        $(this).parent().find(".applyTmtb").show();
-                    }
-                    if(wms.qtyTmtbSq > 0 && wms.applyQtySectionYn == "N") {
-                        $(this).parent().find(".notApplyTmtb .notApplyTmtbNm > ul").append("<li>" + wms.qtyTmtbNm + "<a href=''>대상 상품 보기</a></li>");
-                        $(this).parent().find(".notApplyTmtb").show();
-                    }
-                    if(wms.amtTmtbSq > 0 && wms.applyAmtSectionYn == "N") {
-                        $(this).parent().find(".notApplyTmtb .notApplyTmtbNm > ul").append("<li>" + wms.amtTmtbNm + "<a href=''>대상 상품 보기</a></li>");
-                        $(this).parent().find(".notApplyTmtb").show();
-                    }
-
-                    // 다다익선 할인가 적용
-                    if(wms.tmtbDcAmt < wms.currPrice) {
-                        $(this).parent().find(".info_calc .selling_price").text(Number(wms.tmtbDcAmt).toLocaleString() + " 원");
-                        $(this).parent().find(".info_calc .price").append("<del>" + Number(wms.currPrice).toLocaleString() + " 원</del>");
-                    }
-
-                    if(wms.delvFee == 0) {
-                        $(".wmsList").find(".delv_" + wms.delvFeeCd).html("<div class='info_dlvr'><span class='dlvr_fee'>배송비 무료</span></div>");
-                    } else {
-                        let html = "<div class='info_dlvr'><span class='dlvr_fee'>" + Number(wms.delvFee).toLocaleString() + " 원</span><a href='#' target='_black'>배송비 SAVE 상품 보기</a></div>";
-                        $(".wmsList").find(".delv_" + wms.delvFeeCd).html(html);
-                        // $(".wmsList").find(".delv_" + wms.delvFeeCd).append("<span class='dlvr_shop'>" + wms.supplyCompNm + " 업체직배송</span>");
-
-                    }
-                }
-            });
-        }
-
-        for(let i = 0 ; i < delvList.length ; i++) {
-            cartList.push(delvList[i]);
-            $("#cartListForm .delvCartInfo input[name=cartSq]").each(function() {
-                if(delvList[i].cartSq == $(this).val()) {
-                    let delv = delvList[i];
-                    // $(this).parent().find(".thumb_box img").attr("src", result.imgPath1 + "/" + wms.sysImgNm);
-                    $(this).parent().find(".od_moresale .applyTmtbNm > ul").html("");
-                    $(this).parent().find(".od_moresale .notApplyTmtbNm > ul").html("");
-
-                    // 다다익선 적용 정보 생성성
-                    if(delv.qtyTmtbSq > 0 && delv.applyQtySectionYn == "Y") {
-                        $(this).parent().find(".applyTmtb .applyTmtbNm > ul").append("<li>" + delv.qtyTmtbNm + "</li>");
-                        $(this).parent().find(".applyTmtb").show();
-                    }
-                    if(delv.amtTmtbSq > 0 && delv.applyAmtSectionYn == "Y") {
-                        $(this).parent().find(".applyTmtb .applyTmtbNm > ul").append("<li>" + delv.amtTmtbNm + "</li>");
-                        $(this).parent().find(".applyTmtb").show();
-                    }
-                    if(delv.qtyTmtbSq > 0 && delv.applyQtySectionYn == "N") {
-                        $(this).parent().find(".notApplyTmtb .notApplyTmtbNm > ul").append("<li>" + delv.qtyTmtbNm + "<a href=''>대상 상품 보기</a></li>");
-                        $(this).parent().find(".notApplyTmtb").show();
-                    }
-                    if(delv.amtTmtbSq > 0 && delv.applyAmtSectionYn == "N") {
-                        $(this).parent().find(".notApplyTmtb .notApplyTmtbNm > ul").append("<li>" + delv.amtTmtbNm + "<a href=''>대상 상품 보기</a></li>");
-                        $(this).parent().find(".notApplyTmtb").show();
-                    }
-
-                    // 다다익선 할인가 적용
-                    if(delv.tmtbDcAmt < delv.currPrice) {
-                        $(this).parent().find(".info_calc .selling_price").text(Number(delv.tmtbDcAmt).toLocaleString() + " 원");
-                        $(this).parent().find(".info_calc .price").append("<del>" + Number(delv.currPrice).toLocaleString() + " 원</del>");
-                    }
-
-                    if(delv.delvFee == 0) {
-                        $(".delvList").find(".delv_" + delv.delvFeeCd).html("<div class='info_dlvr'><span class='dlvr_fee'>배송비 무료</span></div>");
-                    } else {
-                        let html = "<div class='info_dlvr'><span class='dlvr_fee'>" + Number(delv.delvFee).toLocaleString() + " 원</span><span class='dlvr_shop'>" + delv.supplyCompNm + " 업체직배송</span><a href='#' target='_black'>배송비 SAVE 상품 보기</a></div>";
-                        $(".delvList").find(".delv_" + delv.delvFeeCd).html(html);
-                    }
-                }
-            });
-        }
-
-        // 결제 총액 영역 수정
-        $("#cartListForm .sumCurrPrice").text(Number(order.sumOrdAmt).toLocaleString());
-        $("#cartListForm .totDelvFee").text(Number(order.totDelvFee).toLocaleString());
-        sumRealPayAmt = order.sumRealPayAmt + order.totDelvFee;
-        totDcAmt = order.totDcAmt;
-
-        // 할인코드 쿠폰 금액 재확인
-        if($("#cartListForm #serialCpnNm").val()) {
-            alert(1);
-            serialCpnApply();
-        } else {
-            $("#cartListForm .totDcAmt").text(Number(order.totDcAmt).toLocaleString());
-            $("#cartListForm .sumRealPayAmt").text(Number(order.sumRealPayAmt + order.totDelvFee).toLocaleString());
-            cancelCartCpn();
-        }
-
-        let notApplyQtyTmtbList = new Array();
-        let notApplyAmtTmtbList = new Array();
-        for(let i = 0 ; i < cartList.length ; i++) {
-            let cart = cartList[i];
-            if(cart.applyQtySectionYn == "N") {
-                let obj = new Object();
-                obj.tmtbSq = cart.qtyTmtbSq;
-                obj.tmtbNm = cart.qtyTmtbNm;
-                obj.currPrice = cart.currPrice;
-                obj.goodsNm = cart.goodsNm;
-                obj.brandNm = cart.brandNm;
-                obj.imgPath = order.imgPath1 + "/" + cart.sysImgNm;
-
-                notApplyQtyTmtbList.push(obj);
-            }
-
-            if(cart.applyAmtSectionYn == "N") {
-                let obj = new Object();
-                obj.tmtbSq = cart.amtTmtbSq;
-                obj.tmtbNm = cart.amtTmtbNm;
-
-                notApplyAmtTmtbList.push(obj);
-            }
-        }
-
-        // 수량 다다익선 정렬
-        var t = new Object();
-        for (let i = 0; i < notApplyQtyTmtbList.length; i++) {
-            for (let j = 0; j < notApplyQtyTmtbList.length - i - 1; j++) {
-                if (notApplyQtyTmtbList[j].tmtbSq > notApplyQtyTmtbList[j + 1].tmtbSq) {
-                    t = notApplyQtyTmtbList[j];
-                    notApplyQtyTmtbList[j] = notApplyQtyTmtbList[j + 1];
-                    notApplyQtyTmtbList[j + 1] = t;
-                }
-            }
-        }
-
-        // 다다익선 적용 대상 상품 노출
-        fnCreateNotApplyTmtbAreaList(notApplyQtyTmtbList, notApplyAmtTmtbList);
-    }
-
-    //옵션변경 팝업열기
-    $(document).on('click','.btn_opt_pop',function(e){
-        $("#optModifyPop").modal("show");
-        return false;
-    });
-
-    //상품옵션변경 팝업 > 수량조절
-    $(document).on('click','.opt_modify_pop .number_count .minus',function(e){
-        var $input = $(this).parent().find('input');
-        var count = parseInt($input.val()) - 1;
-        count = count < 1 ? 1 : count;
-        $input.val(count);
-        $input.change();
-        return false;
-    }).on('click','.opt_modify_pop .number_count .plus',function(e){
-        var $input = $(this).parent().find('input');
-        $input.val(parseInt($input.val()) + 1);
-        $input.change();
-        return false;
-    });
-
-    //상품옵션변경 팝업 > 컬러선택 표기
-    $(document).on('click','.opt_modify_pop .opt_color ul li a',function(e){
-        $(this).parents('.opt_color').find('li a').removeClass('on');
-        $(this).addClass('on');
-        var optColor = $('.opt_modify_pop .opt_color ul li a.on img').attr('alt');
-        $('.opt_modify_pop .opt_color .opt_header .color').text(optColor);
-        return false;
-    });
+	let sumRealPayAmt = [[${order.sumRealPayAmt + order.totDelvFee}]];
+	let totDcAmt = [[${order.totDcAmt}]];
+
+	function NotApplyTmtbCartList() {
+		let tmtbSq = 0;
+		let tmtbNm = "";
+		let goodsList = {
+			brandNm : "",
+			goodsNm : "",
+			currPrice : 0,
+			imgPath : ""
+		}
+	}
+
+	$(document).ready(function() {
+		$("#cartListForm .area_salecoupon .coupon_box").hide();
+		/* TODO 로그인 안했으면 .area_salecoupon (할인코드 입력 부 및 쿠폰정보영역) hide 시킬것 */
+		let loginInfo = [[${loginInfo}]];
+		if(!loginInfo || loginInfo.custNo == null || loginInfo.custNo == 0) {
+			$("#cartListForm .area_salecoupon").hide();
+		}
+
+		// 다다익선 할인 대상(미적용) 리스트
+		notApplyTmtbAreaList();
+	});
+
+	function notApplyTmtbAreaList() {
+		let notApplyQtyTmtbList = new Array();
+		let notApplyAmtTmtbList = new Array();
+
+		// 수량 다다익선 조회
+		$("#cartListForm input[name=qtyTmtbSq]").each(function (index) {
+			if($(this).val() != "0" && $(this).parent().find("input[name=applyQtySectionYn]").val() == "N") {
+				let obj = new Object();
+				obj.tmtbSq = $(this).val();
+				obj.tmtbNm = $(this).parent().find("input[name=qtyTmtbNm]").val();
+				obj.currPrice = $(this).parent().find("input[name=currPrice]").val();
+				obj.goodsNm = $(this).parent().find(".info_box").find(".name").text();
+				obj.brandNm = $(this).parent().find(".info_box").find(".brand").text();
+				obj.imgPath = $(this).parent().find(".info_item").find(".thumb_box img").attr("src");
+
+				notApplyQtyTmtbList.push(obj);
+			}
+
+			if($(this).parent().find("input[name=applyAmtSectionYn]").val() == "N") {       // 다다익선 금액은 기본상품만 가져오면됨 (N은 기본상품에 걸려있음)
+				let obj = new Object();
+				obj.tmtbSq = $(this).parent().find("input[name=amtTmtbSq]").val();
+				obj.tmtbNm = $(this).parent().find("input[name=amtTmtbNm]").val();
+
+				notApplyAmtTmtbList.push(obj);
+			}
+		});
+
+		// 수량 다다익선 정렬
+		var t = new Object();
+		for (let i = 0; i < notApplyQtyTmtbList.length; i++) {
+			for (let j = 0; j < notApplyQtyTmtbList.length - i - 1; j++) {
+				if (notApplyQtyTmtbList[j].tmtbSq > notApplyQtyTmtbList[j + 1].tmtbSq) {
+					t = notApplyQtyTmtbList[j];
+					notApplyQtyTmtbList[j] = notApplyQtyTmtbList[j + 1];
+					notApplyQtyTmtbList[j + 1] = t;
+				}
+			}
+		}
+
+		fnCreateNotApplyTmtbAreaList(notApplyQtyTmtbList, notApplyAmtTmtbList);
+	}
+
+	function fnCreateNotApplyTmtbAreaList(notApplyQtyTmtbList, notApplyAmtTmtbList) {
+		// 정렬 후 같은 다다익선 상품은 한 배열로 묶음
+		let tmtbQtyList = new Array();
+
+		for (let i = 0; i < notApplyQtyTmtbList.length; i++) {
+			let goods = notApplyQtyTmtbList[i];
+			let tmtbInfo = new Object();
+			let chk = false;
+			for (let j = 0; j < tmtbQtyList.length; j++) {
+				let tmtb = tmtbQtyList[j];
+				if (goods.tmtbSq == tmtb.tmtbSq) {
+					tmtbInfo = tmtbQtyList[j];
+					chk = true;
+				}
+			}
+
+			// 현재 상품 정보
+			let goodsInfo = new Object();
+			goodsInfo.brandNm = goods.brandNm;
+			goodsInfo.goodsNm = goods.goodsNm;
+			goodsInfo.imgPath = goods.imgPath;
+			goodsInfo.currPrice = goods.currPrice;
+
+			// 현재 상품 정보 다다익선 정보에 세팅
+			if (chk) {
+				tmtbInfo.goodsList.push(goodsInfo);
+			} else {
+				let obj = new Object();
+				obj.tmtbSq = goods.tmtbSq;
+				obj.tmtbNm = goods.tmtbNm;
+				obj.goodsList = new Array();
+				obj.goodsList.push(goodsInfo);
+				tmtbQtyList.push(obj);
+			}
+		}
+
+		// 수량 다다익선 HTML 작성
+		let tmtbHtml = "";
+		for(let i = 0 ; i < tmtbQtyList.length ; i++) {
+			let tmtb = tmtbQtyList[i];
+			tmtbHtml += '<div class="more_sale qtyNotApplyTmtbList">';
+			for(let j = 0 ; j < tmtb.goodsList.length ; j++) {
+				let goods = tmtb.goodsList[j];
+				tmtbHtml += '<div class="item_gd">\n' +
+					'                <figure>\n' +
+					'                    <a href="">\n' +
+					'                        <span class="thumb"><img src="';
+				tmtbHtml += goods.imgPath;
+				tmtbHtml += '" alt=""></span>\n' +
+					'                    </a>\n' +
+					'                    <figcaption>\n' +
+					'                        <a href="">\n' +
+					'                            <div class="brand">';
+				tmtbHtml += goods.brandNm;
+				tmtbHtml += '</div>\n' +
+					'                            <div class="name">';
+				tmtbHtml += goods.goodsNm;
+				tmtbHtml += '</div>\n' +
+					'                            <div class="price">\n' +
+					'                                <span class="selling_price">';
+				tmtbHtml += Number(goods.currPrice).toLocaleString();
+				tmtbHtml += '</span>\n' +
+					'                            </div>\n' +
+					'                        </a>\n' +
+					'                    </figcaption>\n' +
+					'                </figure>\n' +
+					'            </div>';
+			}
+
+			tmtbHtml += '<div class="txt">\n' +
+				'                <a href="">\n' +
+				'                    <i class="ico ico_saletag"></i>\n' +
+				'                    <input type="hidden" name="tmtbSq" value="' + tmtb.tmtbSq + '" />' +
+				'                    <span>\n';
+			tmtbHtml += tmtb.tmtbNm;
+			tmtbHtml += '</span>\n' +
+				'                </a>\n' +
+				'            </div>\n' +
+				'        </div>';
+		}
+
+		// 금액 다다익선 정보 HTML 작성
+		for(let i = 0 ; i < notApplyAmtTmtbList.length ; i++) {
+			if (notApplyAmtTmtbList[i].tmtbSq != 0) {
+				let tmtb = notApplyAmtTmtbList[i];
+				tmtbHtml += '<div class="more_sale amtNotApplyTmtbList">\n' +
+					'            <div class="txt">\n' +
+					'                <a href="">\n' +
+					'                    <i class="ico ico_saletag"></i>\n' +
+					'                    <input type="hidden" name="tmtbSq" value="' + tmtb.tmtbSq + '" />' +
+					'                    <span>';
+				tmtbHtml += tmtb.tmtbNm;
+				tmtbHtml += '</span>\n' +
+					'                </a>\n' +
+					'            </div>\n' +
+					'        </div>';
+			}
+		}
+
+		if(tmtbHtml != "") {
+			tmtbHtml = "<h4>다다익선 할인 대상이 있습니다.</h4>" + tmtbHtml;
+		}
+
+		$(".area_saleitem").html(tmtbHtml);
+	}
+
+	function cancelCartCpn() {
+		$("#cartListForm #sumRealPayAmt").text(Number(sumRealPayAmt).toLocaleString());
+		$("#cartListForm #totDcAmt").text(Number(totDcAmt).toLocaleString());
+		$("#cartListForm .area_salecoupon .coupon_box").hide();
+	}
+
+	function serialCpnApply() {
+		let cartArr = [];
+		let currPrices = [];
+		$("#cartListForm input[name=cartSqArr]:checked").each(function(index, item) {
+			cartArr.push($(this).val());
+			currPrices.push($(this).parents(".cartInfo").find("input[name=tmtbDcAmt]").val());
+		});
+
+		let data = {
+			rdCpnNm : $("#cartListForm #serialCpnNm").val(),
+			cartSqArr : cartArr,
+			currPrices : currPrices
+		}
+
+		let jsonData = JSON.stringify(data);
+
+		$.ajax( {
+			type: "POST",
+			url : '/cart/list/serialCpnApply',
+			contentType: 'application/json',
+			dataType : 'json',
+			data : jsonData,
+			success : function(result) {
+				$("#cartListForm .area_salecoupon .coupon_box").show();
+
+				// 합계 금액
+				$("#cartListForm #sumRealPayAmt").text(Number(sumRealPayAmt - result.serialCpnInfo.dcAmt).toLocaleString());
+				$("#cartListForm #totDcAmt").text(Number(totDcAmt - result.serialCpnInfo.dcAmt).toLocaleString());
+
+				// 쿠폰 정보
+				$("#cartListForm .area_salecoupon .cp_name").text(result.serialCpnInfo.cpnNm);
+				$("#cartListForm .area_salecoupon .cp_condition").html(result.serialCpnInfo.cpnDesc + "<span><em class='tag'>1장 보유</em></span>");
+				$("#cartListForm .area_salecoupon .availStdt").text(result.serialCpnInfo.availStdt);
+				$("#cartListForm .area_salecoupon .availEddt").text(result.serialCpnInfo.availEddt);
+				if(result.serialCpnInfo.dcWay == "G240_10") {
+					$("#cartListForm .area_salecoupon .cp_dc_val").html( "<em>" + Number(result.serialCpnInfo.dcVal).toLocaleString() + "</em> 원");
+				} else if (result.serialCpnInfo.dcWay == "G240_11") {
+					$("#cartListForm .area_salecoupon .cp_dc_val").html( "<em>" + result.serialCpnInfo.dcVal + "%</em>");
+				}
+			}
+		});
+	};
+
+	//다다익선 적용내역 보기
+	$(document).on('click','.shopping_bag .part_deliver .btn_moresale',function(e){
+		$(this).toggleClass('active');
+		$(this).parents('.od_moresale').find('.li_moresale').toggle();
+		return false;
+	});
+
+	//관심상품 등록
+	$(document).on('click','.shopping_bag .part_deliver .btn_favorite',function(e){
+		$(this).toggleClass('active');
+		return false;
+	});
+
+	function deleteCartAjax(cartArr) {
+		if(cartArr.length < 1) {
+			mcxDialog.alert("삭제하실 상품을 선택해 주세요.");
+			return false;
+		}
+
+		let data = {
+			cartSqArr : cartArr
+		}
+
+		let jsonData = JSON.stringify(data);
+
+		$.ajax( {
+			type: "POST",
+			url : '/cart/deleteCart',
+			contentType: 'application/json',
+			dataType : 'json',
+			data : jsonData,
+			success : function(result) {
+				mcxDialog.alert("삭제 되었습니다.");
+				getCartList();
+			}
+		});
+	}
+
+	function deleteCart(gbn) {
+		let cartArr = [];
+		let confirmMessage = "";
+		if(gbn == "WMS_SELECT") {
+			$("#cartListForm .wmsList input[name=cartSqArr]:checked").each(function () {
+				cartArr.push($(this).val());
+			});
+
+			confirmMessage = "총 " + cartArr.length + "개의 상품을 삭제합니다.";
+		} else if(gbn == "DELV_SELECT") {
+			$("#cartListForm .delvList input[name=cartSqArr]:checked").each(function () {
+				cartArr.push($(this).val());
+			});
+
+			confirmMessage = "총 " + cartArr.length + "개의 상품을 삭제합니다.";
+		} else if(gbn == "WMS_ALL") {
+			$("#cartListForm .wmsList input[name=cartSqArr]").each(function() {
+				cartArr.push($(this).val());
+			});
+
+			confirmMessage = "총알배송상품을 전부 삭제하시겠습니까?";
+		} else if(gbn == "DELV_ALL") {
+			$("#cartListForm .delvList input[name=cartSqArr]").each(function() {
+				cartArr.push($(this).val());
+			});
+
+			confirmMessage = "업체직배송 상품을 전부 삭제하시겠습니까?";
+		} else {
+			cartArr.push(gbn);
+			deleteCartAjax(cartArr);
+			return false;
+		}
+
+		mcxDialog.confirm(confirmMessage, {
+			cancelBtnText: "취소/닫기",		//취소 또는 닫기 버튼명
+			sureBtnText  : "확인",				//처리문 버튼명
+			sureBtnClick : function () {
+				deleteCartAjax(cartArr);
+			}
+		});
+	}
+
+	//쿠폰사용안내 팝업열기
+	$(document).on('click','#btn_cpinfo_pop',function(e){
+		$("#cpinfoPop").modal("show");
+		return false;
+	});
+
+	$("input[name=cartSqArr]").on("change", function(e) {
+		let cartArr = [];
+
+		// 선택된 장바구니 번호
+		$("#cartListForm input[name=cartSqArr]:checked").each(function () {
+			cartArr.push($(this).val());
+		});
+
+		// 선택된 장바구니 정보 가공
+		let data = {    cartSqArr : cartArr }
+		let jsonData = JSON.stringify(data);
+
+		$.ajax( {
+			type: "POST",
+			url : '/cart/change/goods/list',
+			contentType: 'application/json',
+			dataType : 'json',
+			data : jsonData,
+			success : function(result) {
+				fnChangeCartListInfo(result);
+			}
+		});
+	});
+
+	function fnChangeCartListInfo(order) {
+		let wmsList = order.wmsCartList;
+		let delvList = order.delvCartList;
+		let cartList = new Array();
+
+		// 다다익선 정보 숨김
+		$("#cartListForm .applyTmtb").hide();
+		$("#cartListForm .notApplyTmtb").hide();
+
+		// 장바구니 각 상품 가격 정보 할인 전으로 변경
+		$("#cartListForm .cartInfo input[name=cartSq]").each(function() {
+			if($(this).parent().find(".info_calc .price > del").text() != "") {
+				$(this).parent().find(".info_calc .selling_price").text($(this).parent().find(".info_calc .price > del").text());
+				$(this).parent().find(".info_calc .price > del").remove();
+			}
+		});
+		$("#cartListForm").find(".delvFeeArea").html("<div class='info_dlvr'><span class='dlvr_fee'>배송비 무료</span></div>");
+
+		for(let i = 0 ; i < wmsList.length ; i++) {
+			cartList.push(wmsList[i]);
+			$("#cartListForm .wmsCartInfo input[name=cartSq]").each(function() {
+				if(wmsList[i].cartSq == $(this).val()) {
+					let wms = wmsList[i];
+					// $(this).parent().find(".thumb_box img").attr("src", result.imgPath1 + "/" + wms.sysImgNm);
+					$(this).parent().find(".od_moresale .applyTmtbNm > ul").html("");
+					$(this).parent().find(".od_moresale .notApplyTmtbNm > ul").html("");
+
+					// 다다익선 적용 정보 생성성
+					if(wms.qtyTmtbSq > 0 && wms.applyQtySectionYn == "Y") {
+						$(this).parent().find(".applyTmtb .applyTmtbNm > ul").append("<li>" + wms.qtyTmtbNm + "</li>");
+						$(this).parent().find(".applyTmtb").show();
+					}
+					if(wms.amtTmtbSq > 0 && wms.applyAmtSectionYn == "Y") {
+						$(this).parent().find(".applyTmtb .applyTmtbNm > ul").append("<li>" + wms.amtTmtbNm + "</li>");
+						$(this).parent().find(".applyTmtb").show();
+					}
+					if(wms.qtyTmtbSq > 0 && wms.applyQtySectionYn == "N") {
+						$(this).parent().find(".notApplyTmtb .notApplyTmtbNm > ul").append("<li>" + wms.qtyTmtbNm + "<a href=''>대상 상품 보기</a></li>");
+						$(this).parent().find(".notApplyTmtb").show();
+					}
+					if(wms.amtTmtbSq > 0 && wms.applyAmtSectionYn == "N") {
+						$(this).parent().find(".notApplyTmtb .notApplyTmtbNm > ul").append("<li>" + wms.amtTmtbNm + "<a href=''>대상 상품 보기</a></li>");
+						$(this).parent().find(".notApplyTmtb").show();
+					}
+
+					// 다다익선 할인가 적용
+					if(wms.tmtbDcAmt < wms.currPrice) {
+						$(this).parent().find(".info_calc .selling_price").text(Number(wms.tmtbDcAmt).toLocaleString() + " 원");
+						$(this).parent().find(".info_calc .price").append("<del>" + Number(wms.currPrice).toLocaleString() + " 원</del>");
+					}
+
+					if(wms.delvFee == 0) {
+						$(".wmsList").find(".delv_" + wms.delvFeeCd).html("<div class='info_dlvr'><span class='dlvr_fee'>배송비 무료</span></div>");
+					} else {
+						let html = "<div class='info_dlvr'><span class='dlvr_fee'>" + Number(wms.delvFee).toLocaleString() + " 원</span><a href='#' target='_black'>배송비 SAVE 상품 보기</a></div>";
+						$(".wmsList").find(".delv_" + wms.delvFeeCd).html(html);
+						// $(".wmsList").find(".delv_" + wms.delvFeeCd).append("<span class='dlvr_shop'>" + wms.supplyCompNm + " 업체직배송</span>");
+
+					}
+				}
+			});
+		}
+
+		for(let i = 0 ; i < delvList.length ; i++) {
+			cartList.push(delvList[i]);
+			$("#cartListForm .delvCartInfo input[name=cartSq]").each(function() {
+				if(delvList[i].cartSq == $(this).val()) {
+					let delv = delvList[i];
+					// $(this).parent().find(".thumb_box img").attr("src", result.imgPath1 + "/" + wms.sysImgNm);
+					$(this).parent().find(".od_moresale .applyTmtbNm > ul").html("");
+					$(this).parent().find(".od_moresale .notApplyTmtbNm > ul").html("");
+
+					// 다다익선 적용 정보 생성성
+					if(delv.qtyTmtbSq > 0 && delv.applyQtySectionYn == "Y") {
+						$(this).parent().find(".applyTmtb .applyTmtbNm > ul").append("<li>" + delv.qtyTmtbNm + "</li>");
+						$(this).parent().find(".applyTmtb").show();
+					}
+					if(delv.amtTmtbSq > 0 && delv.applyAmtSectionYn == "Y") {
+						$(this).parent().find(".applyTmtb .applyTmtbNm > ul").append("<li>" + delv.amtTmtbNm + "</li>");
+						$(this).parent().find(".applyTmtb").show();
+					}
+					if(delv.qtyTmtbSq > 0 && delv.applyQtySectionYn == "N") {
+						$(this).parent().find(".notApplyTmtb .notApplyTmtbNm > ul").append("<li>" + delv.qtyTmtbNm + "<a href=''>대상 상품 보기</a></li>");
+						$(this).parent().find(".notApplyTmtb").show();
+					}
+					if(delv.amtTmtbSq > 0 && delv.applyAmtSectionYn == "N") {
+						$(this).parent().find(".notApplyTmtb .notApplyTmtbNm > ul").append("<li>" + delv.amtTmtbNm + "<a href=''>대상 상품 보기</a></li>");
+						$(this).parent().find(".notApplyTmtb").show();
+					}
+
+					// 다다익선 할인가 적용
+					if(delv.tmtbDcAmt < delv.currPrice) {
+						$(this).parent().find(".info_calc .selling_price").text(Number(delv.tmtbDcAmt).toLocaleString() + " 원");
+						$(this).parent().find(".info_calc .price").append("<del>" + Number(delv.currPrice).toLocaleString() + " 원</del>");
+					}
+
+					if(delv.delvFee == 0) {
+						$(".delvList").find(".delv_" + delv.delvFeeCd).html("<div class='info_dlvr'><span class='dlvr_fee'>배송비 무료</span></div>");
+					} else {
+						let html = "<div class='info_dlvr'><span class='dlvr_fee'>" + Number(delv.delvFee).toLocaleString() + " 원</span><span class='dlvr_shop'>" + delv.supplyCompNm + " 업체직배송</span><a href='#' target='_black'>배송비 SAVE 상품 보기</a></div>";
+						$(".delvList").find(".delv_" + delv.delvFeeCd).html(html);
+					}
+				}
+			});
+		}
+
+		// 결제 총액 영역 수정
+		$("#cartListForm .sumCurrPrice").text(Number(order.sumOrdAmt).toLocaleString());
+		$("#cartListForm .totDelvFee").text(Number(order.totDelvFee).toLocaleString());
+		sumRealPayAmt = order.sumRealPayAmt + order.totDelvFee;
+		totDcAmt = order.totDcAmt;
+
+		// 할인코드 쿠폰 금액 재확인
+		if($("#cartListForm #serialCpnNm").val()) {
+			serialCpnApply();
+		} else {
+			$("#cartListForm .totDcAmt").text(Number(order.totDcAmt).toLocaleString());
+			$("#cartListForm .sumRealPayAmt").text(Number(order.sumRealPayAmt + order.totDelvFee).toLocaleString());
+			cancelCartCpn();
+		}
+
+		let notApplyQtyTmtbList = new Array();
+		let notApplyAmtTmtbList = new Array();
+		for(let i = 0 ; i < cartList.length ; i++) {
+			let cart = cartList[i];
+			if(cart.applyQtySectionYn == "N") {
+				let obj = new Object();
+				obj.tmtbSq = cart.qtyTmtbSq;
+				obj.tmtbNm = cart.qtyTmtbNm;
+				obj.currPrice = cart.currPrice;
+				obj.goodsNm = cart.goodsNm;
+				obj.brandNm = cart.brandNm;
+				obj.imgPath = order.imgPath1 + "/" + cart.sysImgNm;
+
+				notApplyQtyTmtbList.push(obj);
+			}
+
+			if(cart.applyAmtSectionYn == "N") {
+				let obj = new Object();
+				obj.tmtbSq = cart.amtTmtbSq;
+				obj.tmtbNm = cart.amtTmtbNm;
+
+				notApplyAmtTmtbList.push(obj);
+			}
+		}
+
+		// 수량 다다익선 정렬
+		var t = new Object();
+		for (let i = 0; i < notApplyQtyTmtbList.length; i++) {
+			for (let j = 0; j < notApplyQtyTmtbList.length - i - 1; j++) {
+				if (notApplyQtyTmtbList[j].tmtbSq > notApplyQtyTmtbList[j + 1].tmtbSq) {
+					t = notApplyQtyTmtbList[j];
+					notApplyQtyTmtbList[j] = notApplyQtyTmtbList[j + 1];
+					notApplyQtyTmtbList[j + 1] = t;
+				}
+			}
+		}
+
+		// 다다익선 적용 대상 상품 노출
+		fnCreateNotApplyTmtbAreaList(notApplyQtyTmtbList, notApplyAmtTmtbList);
+	}
+
+	//옵션변경 팝업열기
+	$(document).on('click','.btn_opt_pop',function(e){
+		$("#optModifyPop").modal("show");
+		return false;
+	});
+
+	//상품옵션변경 팝업 > 수량조절
+	$(document).on('click','.opt_modify_pop .number_count .minus',function(e){
+		var $input = $(this).parent().find('input');
+		var count = parseInt($input.val()) - 1;
+		count = count < 1 ? 1 : count;
+		$input.val(count);
+		$input.change();
+		return false;
+	}).on('click','.opt_modify_pop .number_count .plus',function(e){
+		var $input = $(this).parent().find('input');
+		$input.val(parseInt($input.val()) + 1);
+		$input.change();
+		return false;
+	});
+
+	//상품옵션변경 팝업 > 컬러선택 표기
+	$(document).on('click','.opt_modify_pop .opt_color ul li a',function(e){
+		$(this).parents('.opt_color').find('li a').removeClass('on');
+		$(this).addClass('on');
+		var optColor = $('.opt_modify_pop .opt_color ul li a.on img').attr('alt');
+		$('.opt_modify_pop .opt_color .opt_header .color').text(optColor);
+		return false;
+	});
 </script>
 </html>

+ 6 - 12
src/main/webapp/WEB-INF/views/web/mypage/MypageExchangeFormWeb.html

@@ -126,8 +126,8 @@
 							</tr>
 							<tr>
 								<td>
-									<textarea class="doc_exchange" name="chgMemo" id="chgMemo" placeholder="자세한 사유를 입력해주세요." onkeyup="cfnGetTextLength(this, 500, $('#exchange_cnt'));"></textarea>
-									<p class="txt_cnt"><span id="exchange_cnt" class="c_primary">0</span>/500</p>
+									<textarea class="doc_exchange" name="chgMemo" id="chgMemo" placeholder="자세한 사유를 입력해주세요." onkeyup="cfnGetTextLength(this, 200, $('#exchange_cnt'));"></textarea>
+									<p class="txt_cnt"><span id="exchange_cnt" class="c_primary">0</span>/200</p>
 								</td>
 							</tr>
 							</tbody>
@@ -137,7 +137,7 @@
 				<section class="order_row" id="chgerLocation">
 					<div class="order_tit">
 						<h3 class="subH3">상품 회수지</h3>
-						<span class="del_t">교환받을 상품을 수령할 장소 선택</span>
+						<span class="del_t">택배사에서 반품 상품을 직접 회수할 장소 선택</span>
 						<button type="button" class="btn_popup" onclick="fnChangeDeliveryAddr('chger');"><span>회수지 선택</span></button>
 					</div>
 					<div class="tbl type1">
@@ -201,7 +201,7 @@
 				<section class="order_row">
 					<div class="order_tit">
 						<h3 class="subH3">교환 상품 받으실 주소</h3>
-						<span class="del_t">택배사에서 반품 상품을 직접 회수할 장소 선택</span>
+						<span class="del_t">교환받을 상품을 수령할 장소 선택</span>
 						<button type="button" class="btn_popup" onclick="fnChangeDeliveryAddr('recip');"><span>회수지 선택</span></button>
 					</div>
 					<div class="tbl type1">
@@ -253,19 +253,13 @@
 		// 마이페이지 location 설정
 		fnSetMypageLocation('취소/반품/환불내역', '_PAGE_MYPAGE_CRS_LIST', '교환 신청');
 	});
-	
+
 	// 교환 옵션 변경 팝업
 	var fnChangeOption = function(param) {
 		// TODO
 		// 옵션변경 처리
 	}
-	
-	// 회수지, 교환지 설정 팝업
-	var fnChangeDeliveryAddr = function(param) {
-		// TODO
-		// 회수지, 교환지 설정
-	}
-	
+
 	// 교환 처리
 	var fnExchange = function() {
 		// TODO

+ 65 - 10
src/main/webapp/WEB-INF/views/web/mypage/MypageOrderListFormWeb.html

@@ -39,14 +39,14 @@
 					<div th:class="|rank_icon ${#strings.toLowerCase(customerInfo.custGradeNm)}|" th:text="${#strings.substring(customerInfo.custGradeNm, 0, 1)}"></div>
 					<div class="rank_txt01" th:text="${customerInfo.custGradeNm}"></div>
 					<div class="rank_txt02">
-						<button type="button">등급혜택  보기</button>
-						<button type="button" id="cp_down">등급쿠폰 다운</button>
+						<button type="button" onclick="fnGoToCustomerBenefit();">등급혜택  보기</button>
+						<button type="button" id="cp_down" onclick="fnDownloadCoupon();">등급쿠폰 다운</button>
 					</div>
 				</div>
 				<div class="mem_box">
 					<div class="mem_coupon">
 						<p class="tit">보유쿠폰&nbsp;/&nbsp;<span class="c_primary">만료예정</span></p>
-						<span class="coupon_txt01"><span class="big_txt" th:text="${couponCnt}"></span>장</span>&nbsp;/&nbsp;<span class="coupon_txt02 c_primary" th:text="|${expiredSoonCouponCnt}장|">13장</span>
+						<span class="coupon_txt01"><span class="big_txt" id="couponCnt" th:text="${couponCnt}"></span>장</span>&nbsp;/&nbsp;<span class="coupon_txt02 c_primary" id="expiredSoonCouponCnt" th:text="|${expiredSoonCouponCnt}장|"></span>
 					</div>
 					<div class="mem_point">
 						<p class="tit">STYLE  24 포인트</p>
@@ -65,32 +65,32 @@
 				<ul class="clear">
 					<li>
 						<p class="or_p">주문접수</p>
-						<p class="count"><span th:text="${orderCount.orderReceiptCount}">0</span></p>
+						<p class="count"><span id="orderReceiptCount" th:text="${orderCount.orderReceiptCount}">0</span></p>
 					</li>
 					<li>
 						<p class="or_p">결제완료</p>
-						<p class="count"><span th:text="${orderCount.paymentCompleteCount}">0</span></p>
+						<p class="count"><span id="paymentCompleteCount" th:text="${orderCount.paymentCompleteCount}">0</span></p>
 					</li>
 					<li>
 						<p class="or_p">상품 준비 중</p>
-						<p class="count"><span th:text="${orderCount.goodsPrepareCount}">0</span></p>
+						<p class="count"><span id="goodsPrepareCount" th:text="${orderCount.goodsPrepareCount}">0</span></p>
 					</li>
 					<li>
 						<p class="or_p">배송 준비 중</p>
-						<p class="count"><span th:text="${orderCount.shipPrepareCount}">0</span></p>
+						<p class="count"><span id="shipPrepareCount" th:text="${orderCount.shipPrepareCount}">0</span></p>
 					</li>
 					<li>
 						<p class="or_p">배송 중</p>
-						<p class="count"><span th:text="${orderCount.shippingCount}">0</span></p>
+						<p class="count"><span id="shippingCount" th:text="${orderCount.shippingCount}">0</span></p>
 					</li>
 					<li>
 						<p class="or_p">배송 완료</p>
-						<p class="count"><span th:text="${orderCount.shipCompleteCount}">0</span></p>
+						<p class="count"><span id="shipCompleteCount" th:text="${orderCount.shipCompleteCount}">0</span></p>
 					</li>
 				</ul>
 				<div class="order_right">
 					<p class="or_p">취소/교환/반품</p>
-					<p class="count"><span th:text="${orderCount.cancelCount + orderCount.returnCount + orderCount.exchangeCount}">0</span></p>
+					<p class="count"><span id="orderCrsCount" th:text="${orderCount.cancelCount + orderCount.returnCount + orderCount.exchangeCount}">0</span></p>
 				</div>
 			</div>
 			<!-- //주문 경로 -->
@@ -219,6 +219,61 @@
 			}
 		}
 	}
+	
+	// 등급혜택 보기 클릭 이벤트
+	var fnGoToCustomerBenefit = function() {
+		// TODO
+		// 등급혜택보기 페이지 이동
+	}
+	
+	// 등급쿠폰 다운 클릭 이벤트
+	var fnDownloadCoupon = function() {
+		let url = '/mypage/coupon/download/all';
+
+		let data = {};
+		data.custNo = customerInfo.custNo;
+
+		let jsonData = JSON.stringify(data);
+
+		gagajf.ajaxJsonSubmit(url, jsonData, function() {
+			fnReloadCouponCount();
+		});
+	}
+	
+	// 보유쿠폰 수량 업데이트 처리
+	var fnReloadCouponCount = function() {
+		let url = '/mypage/coupon/count';
+		
+		let data = {};
+		data.custNo = customerInfo.custNo;
+		
+		let jsonData = JSON.stringify(data);
+		
+		gagajf.ajaxJsonSubmit(url, jsonData, function(result) {
+			$('#couponCnt').text(result.couponCnt);
+			$('#expiredSoonCouponCnt').text(result.expiredSoonCouponCnt + '장');
+		});
+	}
+	
+	// 상태값 별 수량 업데이트 처리
+	var fnReloadStatusCount = function() {
+		let url = '/mypage/status/count';
+		
+		let data = {};
+		data.custNo = customerInfo.custNo;
+		
+		let jsonData = JSON.stringify(data);
+		
+		gagajf.ajaxJsonSubmit(url, jsonData, function(result) {
+			$('#orderReceiptCount').text(result.orderCount.orderReceiptCount);
+			$('#paymentCompleteCount').text(result.orderCount.paymentCompleteCount);
+			$('#goodsPrepareCount').text(result.orderCount.goodsPrepareCount);
+			$('#shipPrepareCount').text(result.orderCount.shipPrepareCount);
+			$('#shippingCount').text(result.orderCount.shippingCount);
+			$('#shipCompleteCount').text(result.orderCount.shipCompleteCount);
+			$('#orderCrsCount').text(result.orderCount.cancelCount + result.orderCount.returnCount + result.orderCount.exchangeCount);
+		});
+	}
 /*]]>*/
 </script>
 

+ 335 - 0
src/main/webapp/WEB-INF/views/web/mypage/MypageReturnFormWeb.html

@@ -0,0 +1,335 @@
+<!DOCTYPE html>
+<html lang="ko"
+	xmlns:th="http://www.thymeleaf.org"
+	xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+	layout:decorator="web/common/layout/MypageLayoutWeb">
+<!--
+ *******************************************************************************
+ * @source  : MypageReturnFormWeb.html
+ * @desc    : 마이페이지 > 반품신청 Page
+ *============================================================================
+ * STYLE24
+ * Copyright(C) 2021 TSIT, All rights reserved.
+ *============================================================================
+ * VER  DATE         AUTHOR      DESCRIPTION
+ * ===  ===========  ==========  =============================================
+ * 1.0  2021.02.25   card007     최초 작성
+ *******************************************************************************
+ -->
+<body>
+
+<th:block layout:fragment="content">
+	<div class="my_cont">
+		<div class="sec_head">
+			<h3>반품 신청</h3>
+			<div class="od_detail">
+				(주문번호 : <span class="num" th:text="${ordNo}"></span>)
+			</div>
+		</div>
+		<div class="sec_body mypage_body">
+			<form class="form_wrap" role="form">
+				<div class="order_list">
+					<section class="order_row">
+						<th:block th:if="${orderList}" th:each="oneData, status : ${orderList}">
+							<div class="part_deliver">
+								<div class="tbl_tit">
+									<!-- 주문일/선물일 설정 -->
+									<span class="start_t" th:unless="${oneData.giftPackYn == 'Y'}">주문일</span>
+									<span class="gift_t" th:if="${oneData.giftPackYn == 'Y'}">선물일</span>
+									<!-- //주문일/선물일 설정 -->
+	
+									<span class="order_date" th:text="${oneData.ordDt}"></span>
+	
+									<!-- 배송구분 설정 -->
+									<span class="order_label02" th:if="${oneData.shotDelv}">총알배송</span>
+									<span class="order_label01" th:if="${oneData.selfMall}">STYLE24 일반배송</span>
+									<span class="order_label01" th:if="${oneData.supplyMall}">업체직배송</span>
+									<!-- //배송구분 설정 -->
+									<a href="javascript:void(0)" class="detail_btn" th:attr="ordNo=${oneData.ordNo}" onclick="fnGoToOrderDetail(this)">주문상세보기</a>
+								</div>
+								<th:block th:if="${oneData.orderList}" th:each="order, status : ${oneData.orderList}">
+									<div class="tbl type2">
+										<table id="returnList">
+											<colgroup>
+												<col width="1020">
+												<col width="180">
+											</colgroup>
+											<tbody>
+											<th:block th:if="${order.ordDtlList}" th:each="ordDtl, status : ${order.ordDtlList}" th:with="imageUrl=${@environment.getProperty('upload.goods.view')}">
+												<input type="hidden" name="ordDtlNo" th:value="${ordDtl.ordDtlNo}"/>
+												<input type="hidden" name="ordDtlStat" th:value="${ordDtl.ordDtlStat}"/>
+												<input type="hidden" name="reviewSq" th:value="${ordDtl.reviewSq}"/>
+												<tr>
+													<td>
+														<div class="info_item">
+															<div class="thumb_box">
+																<a href="">
+																	<img th:src="${imageUrl + '/' + ordDtl.sysImgNm}" width="100%" alt="">
+																</a>
+															</div>
+															<div class="info_box">
+																<p class="od_name">
+																	<a href="">
+																		<span class="brand" th:text="${ordDtl.brandNm}"></span>
+																		<span class="name" th:text="${ordDtl.goodsNm}"></span>
+																	</a>
+																</p>
+																<p class="od_opt">
+																	<span class="option"><em th:text="${ordDtl.optCd1}"></em><em th:text="${ordDtl.optCd2}"></em></span>
+																	<span class="count">수량 <em th:text="${ordDtl.ordQty}"></em>개</span>
+																</p>
+															</div>
+															<div class="info_calc">
+																<p class="price">
+																	<span class="selling_price" th:text="|${#numbers.formatInteger(ordDtl.ordAmt, 1, 'COMMA')}원|"></span>
+																</p>
+																<p class="point"><span th:text="${#numbers.formatInteger(ordDtl.savePntAmt, 1, 'COMMA')}"></span>p</p>
+															</div>
+														</div>
+													</td>
+													<td class="cnt_sel">
+														<span class="cnt_t">수량</span>
+														<select class="select_dress" name="chgQty" onchange="fnChangeQty();">
+															<option value="">선택</option>
+															<option th:if="${ordDtl.ordQty > 0}" th:each="num : ${#numbers.sequence(1,ordDtl.ordQty)}" th:value="${num}" th:text="${num}"></option>
+														</select>
+													</td>
+												</tr>
+											</th:block>
+											</tbody>
+										</table>
+									</div>
+								</th:block>
+								<div class="order_confirm">
+									<p class="cf_txt cf_desc c_primary">반품하실 상품의 수량을 선택하신 후 반품 신청을 하실 수 있습니다.</p>
+								</div>
+							</div>
+						</th:block>
+					</section>
+					<section class="order_row">
+						<div class="tbl_tit">
+							<h3 class="subH3">반품 사유</h3>
+						</div>
+						<div class="tbl type1">
+							<table>
+								<colgroup>
+									<col width="*">
+								</colgroup>
+								<tbody>
+								<tr>
+									<td>
+										<select id="mounth" name="chgReason" onchange="fnChangeReason(this);">
+											<option value="">반품 사유를 선택하세요</option>
+											<option th:if="${returnReason}" th:each="oneData, status : ${returnReason}" th:value="${oneData.cd}" th:text="${oneData.cdNm}"></option>
+										</select>
+									</td>
+								</tr>
+								<tr>
+									<td>
+										<textarea class="doc_exchange" name="chgMemo" id="chgMemo" placeholder="자세한 사유를 입력해주세요." onkeyup="cfnGetTextLength(this, 200, $('#return_cnt'));"></textarea>
+										<p class="txt_cnt"><span id="return_cnt" class="c_primary">0</span>/200</p>
+									</td>
+								</tr>
+								</tbody>
+							</table>
+						</div>
+					</section>
+					<section class="order_row">
+						<div class="order_tit">
+							<h3 class="subH3">반품 방식 선택</h3>
+						</div>
+						<div class="tbl type1">
+							<table>
+								<colgroup>
+									<col width="*">
+								</colgroup>
+								<tbody>
+								<tr>
+									<td>
+										<div class="form_field radio_field">
+											<div class="">
+												<input type="radio" name="wdGb" id="withdraw" value="W" onclick="fnChangeWdGb();" checked>
+												<label for="withdraw"><span>방문회수 <b class="c_primary">택배사에서 방문하여 회수</b></span></label>
+											</div>
+											<div class="">
+												<input type="radio" name="wdGb" id="direct" value="D" onclick="fnChangeWdGb();">
+												<label for="direct"><span>직접반송 <b class="c_primary">고객이 직접 반송처리</b></span></label>
+											</div>
+										</div>
+									</td>
+								</tr>
+								</tbody>
+							</table>
+						</div>
+					</section>
+					<section class="order_row" id="chgerLocation">
+						<div class="order_tit">
+							<h3 class="subH3">상품 회수지</h3>
+							<span class="del_t">택배사에서 반품 상품을 직접 회수할 장소 선택</span>
+							<button type="button" class="btn_popup" onclick="fnChangeDeliveryAddr('chger');"><span>회수지 선택</span></button>
+						</div>
+						<div class="tbl type1">
+							<table>
+								<colgroup>
+									<col width="200">
+									<col width="*">
+								</colgroup>
+								<tbody>
+								<tr>
+									<th>성명</th>
+									<td id="chgerNm" th:text="${deliveryAddrInfo.recipNm}"></td>
+									<input type="hidden" name="chgerNm" th:value="${deliveryAddrInfo.recipNm}">
+								</tr>
+								<tr>
+									<th>연락처</th>
+									<td id="chgerPhnno" th:text="${deliveryAddrInfo.recipPhnno}"></td>
+									<input type="hidden" name="chgerPhnno" th:value="${deliveryAddrInfo.recipPhnno}">
+								</tr>
+								<tr>
+									<th>주소</th>
+									<td id="chgerAddr" th:text="|${deliveryAddrInfo.recipBaseAddr} ${deliveryAddrInfo.recipDtlAddr}|"></td>
+									<input type="hidden" name="chgerBaseAddr" th:value="${deliveryAddrInfo.recipBaseAddr}">
+									<input type="hidden" name="chgerDtlAddr" th:value="${deliveryAddrInfo.recipDtlAddr}">
+								</tr>
+								</tbody>
+							</table>
+						</div>
+					</section>
+					<section class="order_row" id="returnLocation" style="display:none">
+						<div class="order_tit">
+							<h3 class="subH3">반품하실 배송지</h3>
+						</div>
+						<div class="tbl type1">
+							<table>
+								<colgroup>
+									<col width="200">
+									<col width="*">
+								</colgroup>
+								<tbody>
+								<tr>
+									<th>성명</th>
+									<td th:text="${deliveryAddrInfo.rtnLocNm}"></td>
+									<input type="hidden" name="rtnLocNm" th:value="${deliveryAddrInfo.rtnLocNm}">
+								</tr>
+								<tr>
+									<th>연락처</th>
+									<td th:text="${deliveryAddrInfo.rtnLocTelno}"></td>
+									<input type="hidden" name="rtnLocTelno" th:value="${deliveryAddrInfo.rtnLocTelno}">
+								</tr>
+								<tr>
+									<th>주소</th>
+									<td th:text="|${deliveryAddrInfo.rtnLocBaseAddr} ${deliveryAddrInfo.rtnLocDtlAddr}|"></td>
+									<input type="hidden" name="rtnLocBaseAddr" th:value="${deliveryAddrInfo.rtnLocBaseAddr}">
+									<input type="hidden" name="rtnLocDtlAddr" th:value="${deliveryAddrInfo.rtnLocDtlAddr}">
+								</tr>
+								</tbody>
+							</table>
+						</div>
+					</section>
+					<section class="order_row">
+						<div class="order_tit">
+							<h3 class="subH3">환불 정보</h3>
+							<button type="button" class="btn_popup"><span>취소 전표 보기</span></button>
+						</div>
+						<div class="tbl type1 re_info_tbl">
+							<div class="r_left">
+								<dl>
+									<dt>환불(예정) 금액</dt>
+									<dd>
+										<span class="big_t"><strong id="returnAmt">0</strong>원</span>
+									</dd>
+								</dl>
+								<dl>
+									<dt>상품취소 금액</dt>
+									<dd>
+										<span id="goodsCancelAmt">0</span>원
+									</dd>
+								</dl>
+								<dl>
+									<dt>배송비</dt>
+									<dd>
+										<span id="deliveryFee">0</span>원
+									</dd>
+								</dl>
+								<dl>
+									<dt>할인금액 차감</dt>
+									<dd>
+										<span id="deductDcAmt">0</span>원
+									</dd>
+								</dl>
+							</div>
+							<div class="r_right">
+								<dl>
+									<dt>환불수단</dt>
+									<dd>
+										<span th:text="${paymentInfo.payMeansNm}"></span>
+									</dd>
+								</dl>
+								<dl>
+									<dt>결제금액 환불</dt>
+									<dd>
+										<span id="refundPayAmt">0</span>원
+									</dd>
+								</dl>
+								<dl>
+									<dt>포인트 환불</dt>
+									<dd>
+										<span id="refundPoint">0</span>P
+									</dd>
+								</dl>
+								<dl>
+									<dt>상품권 환불</dt>
+									<dd>
+										<span id="refundGiftCard">0</span>원
+									</dd>
+								</dl>
+							</div>
+						</div>
+						<p class="alert_t">※ 카드사로 결제 취소 요청이 전달된 후 환불까지는 평일 기준 3 ~7일이 소요될 수 있습니다.</p>
+					</section>
+					<section class="order_row" id="addDeliveryFee" style="display:none">
+						<div class="ship_fee">
+							<p><span class="c_primary" id="addPayCost">2,500원</span> 배송비 추가 결제가 필요합니다.</p>
+							<input type="hidden" name="addPayCost"/>
+						</div>
+					</section>
+					<div class="btn_wrap">
+						<button type="button" class="btn btn_default cancle_btn" onclick="cfnGoToPage(_PAGE_MYPAGE_CRS_LIST)"><span>반품 취소</span></button>
+						<button tyep="submit" class="btn btn_primary submit_btn" onclick="fnReturn()"><span id="returnButton">반품 신청</span></button>
+					</div>
+				</div>
+			</form>
+		</div>
+	</div>
+<script src="/ux/plugins/gaga/gaga.paging.js"></script>
+<script th:inline="javascript">
+	$(document).ready(function() {
+		// 마이페이지 LNB 설정
+		fnSetMypageLnbList(2);
+		
+		// 마이페이지 location 설정
+		fnSetMypageLocation('취소/반품/환불내역', '_PAGE_MYPAGE_CRS_LIST', '반품 신청');
+	});
+	
+	// 반품 처리
+	var fnReturn = function() {
+		// TODO
+		// 반품신청 처리
+	}
+	
+	// 반품 수량 변경 이벤트 처리
+	var fnChangeQty = function(param) {
+		// TODO
+		// 반품 수량 변경 처리
+	}
+	
+	var fnChangeWdGb = function() {
+		let wdGb = $('input[name=wdGb]:radio:checked').val();
+		console.log(wdGb);
+	}
+</script>
+
+</th:block>
+
+</body>
+</html>

+ 11 - 1
src/main/webapp/ux/pc/js/cart.js

@@ -43,7 +43,11 @@ var fnDecideOrder = function(param) {
 			gagajf.ajaxJsonSubmit('/mypage/order/decision'
 				, jsonData
 				, function() {
-					cfnGoToPage(_PAGE_MYPAGE_ORDER_DETAIL + ordNo);
+					if (typeof(fnReloadStatusCount) == 'function') {
+						fnReloadStatusCount();
+					} else {
+						cfnGoToPage(_PAGE_MYPAGE_ORDER_DETAIL + ordNo);
+					}
 				});
 		}
 	});
@@ -189,6 +193,12 @@ var fnDeleteOrder = function() {
 	});
 };
 
+// 회수지, 교환지 설정 팝업
+var fnChangeDeliveryAddr = function(param) {
+	// TODO
+	// 회수지, 교환지 설정
+}
+
 // 문자열 길이를 체크
 var cfnGetTextLength = function(obj, maxLen, dpLoc) {
 	var valLen = $(obj).val().length;

+ 55 - 2
src/main/webapp/ux/style24_link.js

@@ -58,7 +58,7 @@ const _PAGE_NOTICE = _frontUrl + "/callcenter/notice/form";								// 고객센
  * @access : public
  * @desc   : page 이동
  * <pre>
- *		 cfnGoToPage(PAGE_LOGIN);
+ *     cfnGoToPage(PAGE_LOGIN);
  * </pre>
  * @param  : page - page
  * @return : None
@@ -179,7 +179,7 @@ var cfnOpenIpinCertify = function (redirectUrl) {
  */
 function cfnAddCart(cartList) {
 	let jsonData = JSON.stringify(cartList);
-	
+
 	$.ajax( {
 		type: "POST",
 		url : '/cart/save',
@@ -191,3 +191,56 @@ function cfnAddCart(cartList) {
 		}
 	});
 }
+
+
+/**
+ * @type   : function
+ * @access : public
+ * @desc   :  네이버 로그인
+ * <pre>
+ *     cfnLoginNaver();
+ *     호출된 페이지에서
+ *     PC: fnSnsSigninCallback(userInfo) 콜백 함수 생성 후 가지고 호출 처리
+ *     MO :
+ * </pre>
+ * @since  : 2021/02/23
+ * @author : jsshin
+ */
+var cfnLoginNaver = function (requestGb, chkRememberMe) {
+	var actionUrl = _frontUrl + '/signin/naverlogin?rememberMe=' + chkRememberMe;
+	var popupHeight = 800;
+	var popupWidth = 600;
+	var popupX = (window.screen.width / 2) - (popupWidth / 2);
+	var popupY = (window.screen.height / 3) - (popupHeight / 3);
+	if ('P' === _frontGb) {
+		window.open(actionUrl, 'naverLogin', 'top=' + popupY + ',left=' + popupX + ',height=' + popupHeight + ',width=' + popupWidth + ', fullscreen=no,menubar=no,status=no,toolbar=no,titlebar=yes,location=no,scrollbars=yes', '');
+	} else {
+		document.location.href = actionUrl + '&requestGb=' + requestGb;
+	}
+};
+
+/**
+ * @type   : function
+ * @access : public
+ * @desc   : 카카오 로그인
+ * <pre>
+ *     cfnLoginKakao();
+ *     호출된 페이지에서
+ *     PC: fnSnsSigninCallback(userInfo) 콜백 함수 생성 후 가지고 호출 처리
+ *     MO :
+ * </pre>
+ * @since  : 2021/02/23
+ * @author : jsshin
+ */
+var cfnLoginKakao = function (requestGb, chkRememberMe) {
+	var actionUrl = _frontUrl + '/signin/kakologin?rememberMe=' + chkRememberMe;
+	var popupWidth = 450;
+	var popupHeight = 700;
+	var popupX = (window.screen.width / 2) - (popupWidth / 2);
+	var popupY = (window.screen.height / 3) - (popupHeight / 3);
+	if ('P' === _frontGb) {
+		window.open(actionUrl, 'kakaoLogin', 'top=' + popupY + ',left=' + popupX + ',height=' + popupHeight + ',width=' + popupWidth + ', fullscreen=no,menubar=no,status=no,toolbar=no,titlebar=yes,location=no,scrollbars=yes', '');
+	} else {
+		document.location.href = actionUrl + '&requestGb=' + requestGb;
+	}
+};