Browse Source

Merge branch 'develop' into eskim

Conflicts:
	src/main/java/com/style24/admin/biz/web/TsaMarketingController.java
eskim 5 năm trước cách đây
mục cha
commit
25d429af78
27 tập tin đã thay đổi với 1909 bổ sung142 xóa
  1. 30 0
      src/main/java/com/style24/admin/biz/dao/TsaMorebetterDao.java
  2. 16 0
      src/main/java/com/style24/admin/biz/dao/TsaPgDao.java
  3. 11 0
      src/main/java/com/style24/admin/biz/service/TsaCouponService.java
  4. 35 11
      src/main/java/com/style24/admin/biz/service/TsaMorebetterService.java
  5. 117 0
      src/main/java/com/style24/admin/biz/service/TsaPgService.java
  6. 8 1
      src/main/java/com/style24/admin/biz/web/TsaCustomerController.java
  7. 58 8
      src/main/java/com/style24/admin/biz/web/TsaMarketingController.java
  8. 74 1
      src/main/java/com/style24/admin/biz/web/TsaOrderController.java
  9. 2 0
      src/main/java/com/style24/persistence/domain/CustCoupon.java
  10. 3 0
      src/main/java/com/style24/persistence/domain/MoreBetter.java
  11. 6 0
      src/main/java/com/style24/persistence/domain/MoreBetterGoods.java
  12. 66 0
      src/main/java/com/style24/persistence/domain/OrderSample.java
  13. 43 0
      src/main/java/com/style24/persistence/domain/OrderSampleGoods.java
  14. 22 22
      src/main/java/com/style24/persistence/mybatis/shop/TsaCoupon.xml
  15. 37 42
      src/main/java/com/style24/persistence/mybatis/shop/TsaCustomer.xml
  16. 53 0
      src/main/java/com/style24/persistence/mybatis/shop/TsaMorebetter.xml
  17. 489 0
      src/main/java/com/style24/persistence/mybatis/shop/TsaPg.xml
  18. 2 3
      src/main/webapp/WEB-INF/views/customer/CellphoneChangePopupForm.html
  19. 23 32
      src/main/webapp/WEB-INF/views/customer/CustomerDetailForm.html
  20. 336 0
      src/main/webapp/WEB-INF/views/marketing/CouponIssuePopupForm.html
  21. 12 10
      src/main/webapp/WEB-INF/views/marketing/MorebetterPopupForm.html
  22. 19 8
      src/main/webapp/WEB-INF/views/marketing/PointGrantPopupForm.html
  23. 2 2
      src/main/webapp/WEB-INF/views/order/ExchangeRequestForm.html
  24. 6 0
      src/main/webapp/WEB-INF/views/order/OrderListForm.html
  25. 437 0
      src/main/webapp/WEB-INF/views/order/OrderSamplePopupForm.html
  26. 1 1
      src/main/webapp/ux/css/admin.ui.css
  27. 1 1
      src/main/webapp/ux/plugins/gaga/gaga.paging.js

+ 30 - 0
src/main/java/com/style24/admin/biz/dao/TsaMorebetterDao.java

@@ -7,6 +7,7 @@ import org.apache.ibatis.session.ResultHandler;
 import org.springframework.stereotype.Component;
 
 import java.util.Collection;
+import java.util.List;
 
 /**
  * 마케팅 다다익선 Dao
@@ -222,6 +223,15 @@ public interface TsaMorebetterDao {
      */
     void createTmtbGoodsTemp(MoreBetterGoods moreBetterGoods);
 
+    /**
+     * 다다익선 - 입력받은 다다익선 적용 상품 insert
+     * @param
+     * @return
+     * @author bin2107
+     * @since 2021. 1. 22
+     */
+    void createTmtbApplyGoodsTemp(MoreBetterGoods moreBetterGoods);
+
     /**
      * 다다익선 중복 상품 조회
      * @param moreBetterGoods
@@ -239,5 +249,25 @@ public interface TsaMorebetterDao {
      * @since 2021. 1. 26
      */
     void updateMorebetterStat(MoreBetter moreBetter);
+
+    /**
+     * 다다익선 - 중복제거 적용 상품 리스트 delete
+     * @param
+     * @return
+     * @author bin2107
+     * @since 2021. 1. 22
+     */
+    void deleteTmtbApplyGoodsTemp(MoreBetterGoods moreBetterGoods);
+
+    /**
+     * 다다익선 중복제거 적용 상품 리스트 조회
+     * @param
+     * @return
+     * @author bin2107
+     * @since 2021. 2. 1
+     */
+    List<MoreBetterGoods> getMorebetterRealApplyGoodsList(MoreBetter moreBetter);
+
+    List<MoreBetterGoods> getMorebetterCompBrandGoodsList(MoreBetterGoods moreBetterGoods);
     /* // CSB 진행 */
 }

+ 16 - 0
src/main/java/com/style24/admin/biz/dao/TsaPgDao.java

@@ -1,6 +1,10 @@
 package com.style24.admin.biz.dao;
 
+import java.util.Collection;
+
 import com.style24.core.support.annotation.ShopDs;
+import com.style24.persistence.domain.Goods;
+import com.style24.persistence.domain.OrderSample;
 
 /**
  * 주문관리 Dao
@@ -11,6 +15,18 @@ import com.style24.core.support.annotation.ShopDs;
 @ShopDs
 public interface TsaPgDao {
 
+	/* 주문 샘플 데이터 (추후 삭제 예정) */
+	Collection<Goods> getOrderSampleGoodsInfo(Goods goods);
+	Goods getOrderSampleGoodsStock(Goods goods);
+	int createOrderSample(OrderSample orderSample);
+	int createDelveryAddrSample(OrderSample orderSample);
+	int createDeliveryFeeSample(OrderSample orderSample);
+	int createOrderDetailSample(OrderSample orderSample);
+	int createOrderDetailItemSample(OrderSample orderSample);
+	int createPaymentSample(OrderSample orderSample);
+	int updateDeliveryFeeSample(OrderSample orderSample);
+	/* //주문 샘플 데이터 (추후 삭제 예정) */
+
 }
 
 

+ 11 - 0
src/main/java/com/style24/admin/biz/service/TsaCouponService.java

@@ -409,4 +409,15 @@ public class TsaCouponService {
 	public ArrayList<CustCoupon> getRandomCouponInfo(int cpnId) {
 		return couponDao.getRandomCouponInfo(cpnId);
 	}
+
+	/**
+	 * 회원상세 - 쿠폰발급
+	 * @param coupon - 쿠폰정보
+	 * @author jsshin
+	 * @since 2021. 1. 29
+	 */
+	@Transactional("shopTxnManager")
+	public void saveCouponIssue(CustCoupon coupon) {
+		couponDao.saveCouponCustPub(coupon);
+	}
 }

+ 35 - 11
src/main/java/com/style24/admin/biz/service/TsaMorebetterService.java

@@ -16,6 +16,7 @@ import com.style24.admin.biz.dao.TsaMorebetterDao;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 
 /**
  *마케팅>다다익선 Service
@@ -143,8 +144,6 @@ public class TsaMorebetterService {
         moreBetter.setUpdNo(TsaSession.getInfo().getUserNo());
         Gson gson = new Gson();
         String jsonData = gson.toJson(moreBetter);
-        log.info("{ saveMoreBetterDetail jsonData}",jsonData);
-        log.info("{ saveMoreBetterDetail moreBetter}",moreBetter);
 
         // TMTB 마스터(TB_TMTB) 저장
         morebetterDao.saveMorebetterMst(moreBetter);
@@ -171,16 +170,21 @@ public class TsaMorebetterService {
             morebetterDao.saveMorebetterGoods(regBrand);
         }
 
+        List<MoreBetterGoods> realApplyGoodsList = morebetterDao.getMorebetterRealApplyGoodsList(moreBetter);
         // 적용상품
-        for(MoreBetterGoods regApplyGoods : moreBetter.getApplyGoodsList()){
-            // 다다익선 적용대상 설정(TB_TMTB_GOODS) 저장
-            regApplyGoods.setTmtbSq(moreBetter.getTmtbSq());
-            regApplyGoods.setTargetVal(regApplyGoods.getGoodsCd());
-            regApplyGoods.setRegNo(moreBetter.getRegNo());
-            regApplyGoods.setUpdNo(moreBetter.getUpdNo());
-
-            morebetterDao.saveMorebetterGoods(regApplyGoods);
-            morebetterDao.saveMorebetterApplyGoods(regApplyGoods);
+        for(MoreBetterGoods realApplyGoods : realApplyGoodsList){
+            for(MoreBetterGoods regApplyGoods : moreBetter.getApplyGoodsList()){
+                if(regApplyGoods.getGoodsCd().equals(realApplyGoods.getGoodsCd())){
+                    // 다다익선 적용대상 설정(TB_TMTB_GOODS) 저장
+                    regApplyGoods.setTmtbSq(moreBetter.getTmtbSq());
+                    regApplyGoods.setTargetVal(realApplyGoods.getGoodsCd());
+                    regApplyGoods.setRegNo(moreBetter.getRegNo());
+                    regApplyGoods.setUpdNo(moreBetter.getUpdNo());
+
+                    morebetterDao.saveMorebetterGoods(regApplyGoods);
+                    morebetterDao.saveMorebetterApplyGoods(regApplyGoods);
+                }
+            }
         }
 
         // 제외상품
@@ -338,6 +342,26 @@ public class TsaMorebetterService {
     public void createMorebetterGoodsTemp(MoreBetterGoods moreBetterGoods){
         moreBetterGoods.setRegNo(TsaSession.getInfo().getUserNo());
 
+        morebetterDao.deleteTmtbApplyGoodsTemp(moreBetterGoods);
+
+        List<MoreBetterGoods> applyGoodsList = moreBetterGoods.getApplyGoodsList();
+
+        if(moreBetterGoods.getMultiSupplyCompCd().length > 0 || moreBetterGoods.getMultiBrand().length > 0){
+            List<MoreBetterGoods> compBrandGoodsList = morebetterDao.getMorebetterCompBrandGoodsList(moreBetterGoods);
+            if(compBrandGoodsList.size() > 0){
+
+                for(int i=0; i<compBrandGoodsList.size(); i++){
+                    moreBetterGoods.setGoodsCd(compBrandGoodsList.get(i).getGoodsCd());
+                    morebetterDao.createTmtbApplyGoodsTemp(moreBetterGoods);
+                    applyGoodsList.add(compBrandGoodsList.get(i));
+                }
+            }
+        }
+
+        for(int i=0; i<moreBetterGoods.getMultiApplyGoods().length; i++){
+            moreBetterGoods.setGoodsCd(moreBetterGoods.getMultiApplyGoods()[i]);
+            morebetterDao.createTmtbApplyGoodsTemp(moreBetterGoods);
+        }
         morebetterDao.deleteTmtbGoodsTemp(moreBetterGoods);
         morebetterDao.createTmtbGoodsTemp(moreBetterGoods);
     }

+ 117 - 0
src/main/java/com/style24/admin/biz/service/TsaPgService.java

@@ -1,12 +1,24 @@
 package com.style24.admin.biz.service;
 
+import java.util.Collection;
+
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.env.Environment;
+import org.springframework.data.redis.connection.SortParameters;
 import org.springframework.stereotype.Service;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.gagaframework.web.parameter.GagaMap;
+import com.gagaframework.web.rest.server.GagaResponseStatus;
+import com.style24.admin.biz.dao.TsaPgDao;
 import com.style24.core.biz.dao.TscOrderDao;
+import com.style24.core.support.env.TscConstants;
 import com.style24.core.support.message.TscMessageByLocale;
+import com.style24.persistence.domain.Goods;
+import com.style24.persistence.domain.Order;
+import com.style24.persistence.domain.OrderSample;
+import com.style24.persistence.domain.OrderSampleGoods;
 
 import lombok.extern.slf4j.Slf4j;
 
@@ -32,4 +44,109 @@ public class TsaPgService {
 	@Autowired
 	private ObjectMapper mapper;
 	
+	@Autowired
+	private TsaPgDao pgDao;
+	
+	/* 주문 샘플 데이터 (추후 삭제 예정) */
+	public Collection<Goods> getOrderSampleGoodsInfo(Goods goods) {
+		return pgDao.getOrderSampleGoodsInfo(goods);
+	}
+	
+	public Goods getOrderSampleGoodsStock(Goods goods) {
+		return pgDao.getOrderSampleGoodsStock(goods);
+	}
+	
+	public GagaMap createOrderSample(OrderSample orderSample) {
+		GagaMap result = new GagaMap();
+		
+		int custNo = orderSample.getCustNo();
+		String ordNm = orderSample.getOrdNm();
+		String ordPhnno = orderSample.getOrdPhnno();
+		String ordEmail = orderSample.getOrdEmail();
+		String recipZipcode = orderSample.getRecipZipcode();
+		String recipBaseAddr = orderSample.getRecipBaseAddr();
+		String recipDtlAddr = orderSample.getRecipDtlAddr();
+		
+		
+		OrderSample order = new OrderSample();
+		order.setCustNo(custNo);
+		order.setOrdNm(ordNm);
+		order.setOrdPhnno(ordPhnno);
+		order.setOrdEmail(ordEmail);
+		pgDao.createOrderSample(order);
+		
+		int ordNo = order.getOrdNo();
+		
+		OrderSample deliveryAddr = new OrderSample();
+		deliveryAddr.setOrdNm(ordNm);
+		deliveryAddr.setOrdPhnno(ordPhnno);
+		deliveryAddr.setRecipZipcode(recipZipcode);
+		deliveryAddr.setRecipBaseAddr(recipBaseAddr);
+		deliveryAddr.setRecipDtlAddr(recipDtlAddr);
+		deliveryAddr.setCustNo(custNo);
+		pgDao.createDelveryAddrSample(deliveryAddr);
+		
+		int delvAddrSq = deliveryAddr.getDelvAddrSq();
+
+		int delvFeeSq = 0;
+		int ordDtlNo = 0;
+		for (OrderSampleGoods orderSampleGoods : orderSample.getGoods()) {
+			String goodsCd = orderSampleGoods.getGoodsCd();
+			String compsGoodsCd = orderSampleGoods.getCompsGoodsCd();
+			int ordQty = orderSampleGoods.getOrdQty();
+			String optCd = orderSampleGoods.getOptCd();
+			
+			
+			OrderSample deliveryFee = new OrderSample();
+			deliveryFee.setOrdNo(ordNo);
+			deliveryFee.setDelvFeeGb(TscConstants.DeliveryFeeGb.ORIGIN_DELIVERY_FEE.value());
+			deliveryFee.setCustNo(custNo);
+			deliveryFee.setGoodsCd(goodsCd);
+			pgDao.createDeliveryFeeSample(deliveryFee);
+			
+			if (deliveryFee.getDelvFeeSq() != 0) {
+				delvFeeSq = deliveryFee.getDelvFeeSq();
+			}
+			
+			OrderSample orderDetail = new OrderSample();
+			orderDetail.setOrdNo(ordNo);
+			orderDetail.setOrdDtlStat(TscConstants.OrderDetailStat.PAYMENT_COMPLETE.value());
+			orderDetail.setOrdQty(ordQty);
+			orderDetail.setDelvAddrSq(delvAddrSq);
+			orderDetail.setCustNo(custNo);
+			orderDetail.setGoodsCd(goodsCd);
+			pgDao.createOrderDetailSample(orderDetail);
+
+			if (orderDetail.getOrdDtlNo() != 0) {
+				ordDtlNo = orderDetail.getOrdDtlNo();
+			}
+			
+			OrderSample orderDetailItem = new OrderSample();
+			orderDetailItem.setOrdQty(ordQty);
+			orderDetailItem.setCustNo(custNo);
+			orderDetailItem.setCompsGoodsCd(compsGoodsCd);
+			orderDetailItem.setOptCd(optCd);
+			orderDetailItem.setOrdDtlNo(ordDtlNo);
+			pgDao.createOrderDetailItemSample(orderDetailItem);
+			
+			int ordDtlItemSq = orderDetailItem.getOrdDtlItemSq();
+		}
+		
+		OrderSample payment = new OrderSample();
+		payment.setCustNo(custNo);
+		payment.setOrdNo(ordNo);
+		pgDao.createPaymentSample(payment);
+		
+		int paySq = payment.getPaySq();
+		
+		OrderSample updateDeliveryFee = new OrderSample();
+		updateDeliveryFee.setPaySq(paySq);
+		updateDeliveryFee.setOrdNo(ordNo);
+		pgDao.updateDeliveryFeeSample(updateDeliveryFee);
+
+		result.set("status", GagaResponseStatus.SUCCESS.getCode());
+
+		return result;
+	}
+	/* //주문 샘플 데이터 (추후 삭제 예정) */
 }

+ 8 - 1
src/main/java/com/style24/admin/biz/web/TsaCustomerController.java

@@ -4,12 +4,14 @@ import java.util.Collection;
 
 import com.gagaframework.web.parameter.GagaMap;
 import com.gagaframework.web.security.GagaPasswordEncoder;
+import com.gagaframework.web.util.GagaCryptoUtil;
 import com.gagaframework.web.util.GagaStringUtil;
 import com.style24.admin.biz.service.TsaCustomerService;
 import com.style24.admin.biz.service.TsaKakaoService;
 import com.style24.admin.biz.service.TsaSystemService;
 import com.style24.core.support.env.TscConstants;
 import com.style24.core.support.session.TscSession;
+import com.style24.core.support.util.CryptoUtils;
 import com.style24.persistence.domain.Coupon;
 import com.style24.persistence.domain.CustContactHst;
 import com.style24.persistence.domain.CustGrade;
@@ -372,7 +374,7 @@ public class TsaCustomerController extends TsaBaseController {
 		//mav.addObject("dcWayList", rendererService.getCommonCodeList("G240"));
 
 		// 쿠폰발행사유
-		mav.addObject("pubReasonList", rendererService.getCommonCodeList("G597"));
+		mav.addObject("pubReasonList", rendererService.getCommonCodeList("G068"));
 
 		// 포인트반영상태
 		mav.addObject("pntOccurGbList", rendererService.getCommonCodeList("G069"));
@@ -719,6 +721,11 @@ public class TsaCustomerController extends TsaBaseController {
 	@PostMapping("/delivery/addr/save")
 	@ResponseBody
 	public GagaResponse saveCustomerDeliveryAddr(@RequestBody Delivery delivery) {
+		delivery.setRecipNm(CryptoUtils.encryptAES(delivery.getRecipNm()));
+		delivery.setRecipTelno(CryptoUtils.encryptAES(delivery.getRecipTelno()));
+		delivery.setRecipPhnno(CryptoUtils.encryptAES(delivery.getRecipPhnno()));
+		delivery.setRecipDtlAddr(CryptoUtils.encryptAES(delivery.getRecipDtlAddr()));
+		delivery.setRecipBaseAddr(CryptoUtils.encryptAES(delivery.getRecipBaseAddr()));
 		customerService.saveCustomerDeliveryAddr(delivery);
 		return super.ok(message.getMessage("SUCC_0001"));
 	}

+ 58 - 8
src/main/java/com/style24/admin/biz/web/TsaMarketingController.java

@@ -719,22 +719,23 @@ public class TsaMarketingController extends TsaBaseController {
 			moreBetterGoods.setMultiExceptGoods(moreBetter.getMultiExceptGoods());
 
 			// TMTB_GOODS_TEMP TABLE TRUNCATE -> 다른 다다에서 사용중인 상품 조회 -> INSERT
+			moreBetterGoods.setApplyGoodsList(moreBetter.getApplyGoodsList());
 			morebetterService.createMorebetterGoodsTemp(moreBetterGoods);
+
+			morebetterService.saveMoreBetterDetail(moreBetter);
+
 			// 다른 다다에서 사용중인 상품 조회
 			Collection<MoreBetterGoods> duplicateGoodsList = morebetterService.getMorebetterDuplicateList(moreBetterGoods);
-
 			// SELECT -> 지금 내가 선택한 업체&브랜드 + 적용상품에 해당하는 상품 조회 MINUS TMTB_GOODS_TEMP 상품
 			// 조회 건수 있으면 -> 해당 상품코드 엑셀로 던져주기
 			if(duplicateGoodsList.size() > 0){
 				map.set("duplicateYn","Y");
-				//map.set("message", result);
 				map.set("duplicateGoodsList",duplicateGoodsList);
 			}else{
 				// 조회 건수 없으면 -> 저장으로 넘어감
-				morebetterService.saveMoreBetterDetail(moreBetter);
 				map.set("duplicateYn","N");
-				map.set("message", message.getMessage("SUCC_0001"));
 			}
+			map.set("message", message.getMessage("SUCC_0001"));
 		} catch(Exception e) {
 			e.printStackTrace();
 			map.set("message", message.getMessage("FAIL_0001"));
@@ -916,6 +917,7 @@ public class TsaMarketingController extends TsaBaseController {
 		ModelAndView mav = new ModelAndView();
 
 		mav.addObject("elementCustNo", elementCustNo);
+
 		// 사이트 목록
 		mav.addObject("siteCdList", rendererService.getAvailCommonCodeList("G000"));
 
@@ -949,13 +951,61 @@ public class TsaMarketingController extends TsaBaseController {
 		point.setPntUploadStat(TscConstants.PntUploadStat.APPLY_COMPLETE.value());
 		point.setGvPntAmt(point.getPntAmt());
 		point.setRmPntAmt(point.getPntAmt());
-		String expBedt = point.getExpBeDt().replace("-","");
-		String time = "235959";
-		point.setExpBeDt(expBedt+time);
 		corePointService.saveCustomerPoint(point);
 		return super.ok(message.getMessage("SUCC_0004"));
 	}
 
+	/**
+	 * 쿠폰발급 팝업
+	 * @param elementCustNo - 고객일련번호
+	 * @return ModelAndView
+	 * @author jsshin
+	 * @since 2021. 1. 28
+	 */
+	@GetMapping("/coupon/issue/popup/form")
+	@ResponseBody
+	public ModelAndView couponIssuePopupForm(@RequestParam(value = "elementCustNo") String elementCustNo) {
+		ModelAndView mav = new ModelAndView();
+
+		mav.addObject("elementCustNo", elementCustNo);
+
+		// 사이트 목록
+		mav.addObject("siteList", rendererService.getAvailCommonCodeList("G000"));
+
+		// 사용가능고객구분 목록
+		mav.addObject("usableCustGbList", rendererService.getAvailCommonCodeList("G100"));
+
+		// 쿠폰유형 목록
+		mav.addObject("cpnTypeList", rendererService.getAvailCommonCodeList("G230"));
+
+		// 할인방식 목록
+		mav.addObject("dcWayList", rendererService.getAvailCommonCodeList("G240"));
+
+		// 쿠폰발행사유 조회
+		mav.addObject("cpnPubReasonList", rendererService.getCommonCodeList("G068"));
+
+		mav.setViewName("marketing/CouponIssuePopupForm");
+
+		return mav;
+	}
+
+	/**
+	 * 회원상세 - 쿠폰발급
+	 * @param custCoupon - 쿠폰정보
+	 * @return GagaResponse
+	 * @author jsshin
+	 * @since 2021. 1. 29
+	 */
+	@PostMapping("/coupon/issue/save")
+	@ResponseBody
+	public GagaResponse saveCouponIssue(@RequestBody CustCoupon custCoupon) {
+		Integer userNo = TsaSession.getInfo().getUserNo();
+		custCoupon.setRegNo(userNo);
+		custCoupon.setUpdNo(userNo);
+		couponService.saveCouponIssue(custCoupon);
+		return super.ok(message.getMessage("SUCC_0006"));
+	}
+
 	/**
 	 *   카드관련 작업 시작 - eskim
 	 */
@@ -1017,7 +1067,7 @@ public class TsaMarketingController extends TsaBaseController {
 	}
 
 	/**
-	 * 카드무이자할부 팝업
+	 * 카드목록 팝업
 	 * @param
 	 * @return
 	 * @author eskim

+ 74 - 1
src/main/java/com/style24/admin/biz/web/TsaOrderController.java

@@ -4,8 +4,12 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 
+import javax.jws.WebParam;
 import javax.servlet.http.HttpServletRequest;
 
+import com.gagaframework.web.rest.server.GagaResponseStatus;
+import com.style24.admin.biz.service.TsaCustomerService;
+import com.style24.admin.biz.service.TsaPgService;
 import com.style24.core.biz.service.TscOrderService;
 import com.style24.persistence.TscPageRequest;
 import org.apache.commons.collections4.CollectionUtils;
@@ -33,7 +37,9 @@ import com.style24.admin.biz.service.TsaRendererService;
 import com.style24.admin.support.controller.TsaBaseController;
 import com.style24.admin.support.security.session.TsaSession;
 import com.style24.core.support.message.TscMessageByLocale;
+import com.style24.persistence.domain.Goods;
 import com.style24.persistence.domain.Order;
+import com.style24.persistence.domain.OrderSample;
 
 import lombok.extern.slf4j.Slf4j;
 
@@ -59,6 +65,9 @@ public class TsaOrderController extends TsaBaseController {
 
 	@Autowired
 	private TscOrderService orderService;
+	
+	@Autowired
+	private TsaPgService pgService;
 
 	/**
 	 * 주문목록조회
@@ -72,7 +81,7 @@ public class TsaOrderController extends TsaBaseController {
 		ModelAndView mav = new ModelAndView();
 
 		mav.addObject("siteCdList"		, rendererService.getAvailCommonCodeList("G012"));		// 사이트구분
-		mav.addObject("mallGbList"		, rendererService.getAvailCommonCodeList("G011"));		// 몰구분		
+		mav.addObject("mallGbList"		, rendererService.getAvailCommonCodeList("G011"));		// 몰구분
 		mav.addObject("supplyCompList"	, rendererService.getSupplyCompanyList());				// 공급업제목록
 		mav.addObject("ordStatList"		, rendererService.getAvailCommonCodeList("G012"));		// 주문상태코드
 		mav.addObject("ordDtlStatList"	, rendererService.getAvailCommonCodeList("G013"));		// 주문상세상태코드
@@ -83,6 +92,8 @@ public class TsaOrderController extends TsaBaseController {
 		mav.addObject("siteCdList"		, rendererService.getAvailCommonCodeList("G000"));		// 사이트구분
 		mav.addObject("formalGbList"	, rendererService.getAvailCommonCodeList("G009"));		// 정상/이월
 
+		mav.addObject("userNo"			, TsaSession.getInfo().getUserNo());
+
 		mav.setViewName("order/OrderListForm");
 
 		return mav;
@@ -633,6 +644,68 @@ public class TsaOrderController extends TsaBaseController {
 		orderService.updateOrderChange(order);
 		return super.ok(message.getMessage("SUCC_0002"));
 	}
+
+
+
+
+
+
+
+	/* 주문 샘플 데이터 (추후 삭제 예정) */
+	@GetMapping("/sample/create/form")
+	@ResponseBody
+	public ModelAndView orderSamplePopupForm() {
+		ModelAndView mav = new ModelAndView();
+
+		// 상품상태
+		String[] exceptCds = {"G008_00"};
+		mav.addObject("goodsStatList", rendererService.getCommonCodeList("G008", "Y", exceptCds));
+		// 정상이월
+		mav.addObject("formalGbList", rendererService.getAvailCommonCodeList("G009"));
+		// 시즌
+		mav.addObject("seasonList", rendererService.getAvailCommonCodeList("G006"));
+		
+		mav.setViewName("order/OrderSamplePopupForm");
+		
+		return mav;
+	}
+	
+	@PostMapping("/sample/create")
+	@ResponseBody
+	public GagaMap createOrderSample(@RequestBody OrderSample orderSample) {
+		GagaMap result = new GagaMap();
+		result.set("status", GagaResponseStatus.FAIL.getCode());
+
+		log.info("orderSample >>> {}", orderSample);
+		
+		result = pgService.createOrderSample(orderSample);
+		
+		// 처리 결과 코드에 따른 메세지 설정
+		if (result.get("status").equals(GagaResponseStatus.SUCCESS.getCode())) {
+			result.set("message", message.getMessage("SUCC_0004"));
+		} else {
+			result.set("message", message.getMessage("FAIL_0004"));
+		}
+
+		return result;
+	}
+
+	@PostMapping("/sample/goods/info")
+	@ResponseBody
+	public Collection<Goods> getOrderSampleGoodsInfo(@RequestBody String[] arrGoodsCd) {
+		Goods goods = new Goods();
+		goods.setArrGoodsCd(arrGoodsCd);
+		
+		return pgService.getOrderSampleGoodsInfo(goods);
+	}
+
+	@PostMapping("/sample/goods/stock")
+	@ResponseBody
+	public Goods getOrderSampleGoodsStock(@RequestBody Goods goods) {
+		return pgService.getOrderSampleGoodsStock(goods);
+	}
+	
+	/* //주문 샘플 데이터 (추후 삭제 예정) */
 }
 
 

+ 2 - 0
src/main/java/com/style24/persistence/domain/CustCoupon.java

@@ -29,4 +29,6 @@ public class CustCoupon extends TscBaseDomain {
 
     // 그리드 컬럼
     private String  custList;
+    private String  cpnNm;                  // 쿠폰명
+    private Integer ordNo;                  // 주문번호
 }

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

@@ -77,6 +77,9 @@ public class MoreBetter extends TscBaseDomain {
 	@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
 	private String[] multiExceptGoods;
 
+	@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
+	private String[] multiDuplicateGoods;
+
 	// 날짜+시간
 	private String eventStdt;				// 다다익선시작일시
 	private String eventStHH;				// 다다익선시작일시

+ 6 - 0
src/main/java/com/style24/persistence/domain/MoreBetterGoods.java

@@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonFormat;
 import com.style24.persistence.TscBaseDomain;
 import lombok.Data;
 
+import java.util.Collection;
 import java.util.List;
 
 
@@ -55,6 +56,11 @@ public class MoreBetterGoods extends TscBaseDomain {
 
 	@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
 	private String[] multiExceptGoods;
+
+	@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
+	private String[] multiDuplicateGoods;
+
+	List<MoreBetterGoods> applyGoodsList;
 /*
 	List<MoreBetterGoods> multiSupplyCompCd;
 	List<MoreBetterGoods> multiBrand;

+ 66 - 0
src/main/java/com/style24/persistence/domain/OrderSample.java

@@ -0,0 +1,66 @@
+package com.style24.persistence.domain;
+
+import java.util.Collection;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.style24.persistence.TscBaseDomain;
+
+import lombok.Data;
+
+/**
+ * 주문 샘플 Domain
+ *
+ * @author card007
+ * @since 2021. 01. 30
+ */
+@SuppressWarnings("serial")
+@Data
+public class OrderSample extends TscBaseDomain {
+
+	private int ordNo;
+	private int ordDtlNo;
+	private int ordDtlItemSq;
+	private int delvAddrSq;
+	private int paySq;
+	private int custNo;
+	private String ordNm;
+	private String ordPhnno;
+	private String ordTelno;
+	private String ordEmail;
+	private String recipZipcode;
+	private String recipBaseAddr;
+	private String recipDtlAddr;
+	private String optCd2;
+	private int ordQty;
+	private String delvFeeGb;
+	private String delvFeeCd;
+	private int delvFeeSq;
+	private String ordDtlStat;
+
+	@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
+	private Collection<OrderSampleGoods> goods;
+
+	@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
+	private String[] optCd2s;
+
+	private int no;
+	private String sysImgNm;
+	private String goodsCd;
+	private String compsGoodsCd;
+	private String goodsNm;
+	private String optCd;
+	private int stockQtySum;
+	private String goodsStat;
+	private String styleYear;
+	private String seasonCd;
+	private int listPrice;
+	private int currPrice;
+	private String priceUpdDt;
+	private String erpStockLinkYn;
+	private String formalGb;
+	private String returnableYn;
+	private String regDt;
+	private String regNm;
+	private String updDt;
+	private String updNm;
+}

+ 43 - 0
src/main/java/com/style24/persistence/domain/OrderSampleGoods.java

@@ -0,0 +1,43 @@
+package com.style24.persistence.domain;
+
+import java.util.Collection;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.style24.persistence.TscBaseDomain;
+
+import lombok.Data;
+
+/**
+ * 주문 샘플 상품 Domain
+ *
+ * @author card007
+ * @since 2021. 01. 30
+ */
+@SuppressWarnings("serial")
+@Data
+public class OrderSampleGoods extends TscBaseDomain {
+
+	private int no;
+	private String sysImgNm;
+	private String goodsCd;
+	private String compsGoodsCd;
+	private String goodsNm;
+	private int ordQty;
+	private String optCd;
+	private String optCd2;
+	private int stockQtySum;
+	private String goodsStat;
+	private String styleYear;
+	private String seasonCd;
+	private int listPrice;
+	private int currPrice;
+	private String priceUpdDt;
+	private String erpStockLinkYn;
+	private String formalGb;
+	private String returnableYn;
+	private String regDt;
+	private String regNm;
+	private String updDt;
+	private String updNm;
+
+}

+ 22 - 22
src/main/java/com/style24/persistence/mybatis/shop/TsaCoupon.xml

@@ -543,29 +543,29 @@
 	<insert id="saveCouponCustPub" parameterType="CustCoupon">
 		/* TsaCoupon.saveCouponCustPub */
 		INSERT INTO TB_CUST_COUPON (
-			CUST_NO
-		  , CPN_ID
-		  , AVAIL_STDT
-		  , AVAIL_EDDT
-		  , PUB_REASON
-		  , PUB_REASON_DTL
-          , END_ALIM_SEND_YN
-          , REG_NO
-          , REG_DT
-          , UPD_NO
-          , UPD_DT
+		       CUST_NO
+		     , CPN_ID
+		     , AVAIL_STDT
+		     , AVAIL_EDDT
+		     , PUB_REASON
+		     , PUB_REASON_DTL
+		     , END_ALIM_SEND_YN
+		     , REG_NO
+		     , REG_DT
+		     , UPD_NO
+		     , UPD_DT
 		) VALUES (
-		    #{custNo}
-		  , #{cpnId}
-		  , DATE_FORMAT(#{availStdt} , '%Y-%m-%d')
-		  , DATE_FORMAT(#{availEddt} , '%Y-%m-%d')
-		  , #{pubReason}
-		  , #{pubReasonDtl}
-		  , #{endAlimSendYn}
-		  , #{regNo}
-		  , now()
-		  , #{updNo}
-		  , now()
+		       #{custNo}
+		     , #{cpnId}
+		     , DATE_FORMAT(#{availStdt} , '%Y%m%d%H%i%S')
+		     , DATE_FORMAT(#{availEddt} , '%Y%m%d%H%i%S')
+		     , #{pubReason}
+		     , #{pubReasonDtl}
+		     , #{endAlimSendYn}
+		     , #{regNo}
+		     , NOW()
+		     , #{updNo}
+		     , NOW()
 		)
 	</insert>
 

+ 37 - 42
src/main/java/com/style24/persistence/mybatis/shop/TsaCustomer.xml

@@ -307,7 +307,7 @@
 	</update>
 
 	<!--회원 쿠폰내역  -->
-	<select id="getCustomerCouponList" parameterType="Integer" resultType="Coupon">
+	<select id="getCustomerCouponList" parameterType="Integer" resultType="CustCoupon">
 		/* TsaCustomer.getCustomerCounponList */
 		WITH TAB1 AS (
 		              SELECT O.ORD_NO             AS ORD_NO
@@ -349,11 +349,12 @@
 		     , DATE_FORMAT(CC.AVAIL_EDDT, '%Y%m%d%H%i%S')            AS AVAIL_EDDT
 		     , CC.PUB_REASON
 		     , CC.PUB_REASON_DTL
+		     , CC.END_ALIM_SEND_YN
+		     , E.ORD_NO
 		     , DATE_FORMAT(CC.USED_DT, '%Y%m%d%H%i%S')               AS USED_DT
 		     , FN_GET_USER_NM(CC.REG_NO)                             AS REG_NM
 		     , FN_GET_USER_NM(CC.UPD_NO)                             AS USER_NM
 		     , DATE_FORMAT(CC.REG_DT, '%Y%m%d%H%i%S')                AS REG_DT
-		     , E.ORD_NO
 		FROM   TB_COUPON C
 		INNER JOIN
 		       TB_CUST_COUPON CC
@@ -427,46 +428,40 @@
 	<!--회원 포인트내역  -->
 	<select id="getCustomerPointList" parameterType="Integer" resultType="Point">
 		/* TsaCustomer.getCustomerPointList */
-		SELECT CC.*
-		FROM (
-		      SELECT DATE_FORMAT(CASE WHEN CPH.PNT_UPLOAD_STAT = 'G070_30'
-		                              THEN CPH.PNT_UPLOAD_DT
-		                          ELSE CPH.REG_DT END, '%Y-%m-%d' ) AS DT
-		           , CPH.PNT_HST_SQ
-		           , C.CUST_ID
-		           , C.CUST_NO
-		           , C.SITE_CD
-		           , CPH.OCCUR_GB
-		           , CPH.OCCUR_DTL_DESC
-		           , CPH.PNT_AMT
-		           , CPH.ORD_DTL_NO
-		           , CPH.REVIEW_SQ
-		           , DATE_FORMAT(CPH.SWITCH_DUE_DT, '%Y%m%d%H%i%S')  AS SWITCH_DUE_DT
-		           , CPH.PNT_UPLOAD_STAT
-		           , DATE_FORMAT(CPH.PNT_UPLOAD_DT, '%Y%m%d%H%i%S')  AS PNT_UPLOAD_DT
-		           , IFNULL(FN_GET_USER_NM(CPH.REG_NO), CPH.REG_NO)  AS REG_NM
-		           , DATE_FORMAT(CPH.REG_DT, '%Y%m%d%H%i%S')         AS REG_DT
-		           , IFNULL(FN_GET_USER_NM(CPH.UPD_NO), CPH.UPD_NO)  AS UPD_NM
-		           , DATE_FORMAT(CPH.UPD_DT, '%Y%m%d%H%i%S')         AS UPD_DT
-		           , DATE_FORMAT((
-		                          SELECT MAX(CP.EXP_BE_DT) AS EXP_BE_DT
-		                          FROM   TB_CUST_POINT CP
-		                          WHERE  CP.CUST_PNT_SQ = CPH.CUST_PNT_SQ
-			                      AND    CP.CUST_NO = CPH.CUST_NO
-		              ), '%Y%m%d%H%i%S') AS EXP_BE_DT
-		           , DATE_FORMAT((
-		                          SELECT MAX(CP.EXP_CMP_DT) AS EXP_CMP_DT
-		                          FROM   TB_CUST_POINT CP
-		                          WHERE  CP.CUST_PNT_SQ = CPH.CUST_PNT_SQ
-		                          AND    CP.CUST_NO = CPH.CUST_NO
-		              ), '%Y%m%d%H%i%S') AS EXP_CMP_DT
-		      FROM   TB_CUSTOMER C
-		      INNER JOIN
-		             TB_CUST_POINT_HST CPH
-		      ON     C.CUST_NO = CPH.CUST_NO
-		      WHERE  C.CUST_NO = #{custNo}
-		     ) CC
-		ORDER BY CC.DT DESC
+		SELECT  CPH.PNT_HST_SQ
+		      , C.CUST_ID
+		      , C.CUST_NO
+		      , C.SITE_CD
+		      , CPH.OCCUR_GB
+		      , CPH.OCCUR_DTL_DESC
+		      , CPH.PNT_AMT
+		      , CPH.ORD_DTL_NO
+		      , CPH.REVIEW_SQ
+		      , DATE_FORMAT(CPH.SWITCH_DUE_DT, '%Y%m%d%H%i%S')  AS SWITCH_DUE_DT
+		      , CPH.PNT_UPLOAD_STAT
+		      , DATE_FORMAT(CPH.PNT_UPLOAD_DT, '%Y%m%d%H%i%S')  AS PNT_UPLOAD_DT
+		      , IFNULL(FN_GET_USER_NM(CPH.REG_NO), CPH.REG_NO)  AS REG_NM
+		      , DATE_FORMAT(CPH.REG_DT, '%Y%m%d%H%i%S')         AS REG_DT
+		      , IFNULL(FN_GET_USER_NM(CPH.UPD_NO), CPH.UPD_NO)  AS UPD_NM
+		      , DATE_FORMAT(CPH.UPD_DT, '%Y%m%d%H%i%S')         AS UPD_DT
+		      , DATE_FORMAT((
+		                     SELECT MAX(CP.EXP_BE_DT) AS EXP_BE_DT
+		                     FROM   TB_CUST_POINT CP
+		                     WHERE  CP.CUST_PNT_SQ = CPH.CUST_PNT_SQ
+		                     AND    CP.CUST_NO = CPH.CUST_NO
+		         ), '%Y%m%d%H%i%S') AS EXP_BE_DT
+		      , DATE_FORMAT((
+		                     SELECT MAX(CP.EXP_CMP_DT) AS EXP_CMP_DT
+		                     FROM   TB_CUST_POINT CP
+		                     WHERE  CP.CUST_PNT_SQ = CPH.CUST_PNT_SQ
+		                     AND    CP.CUST_NO = CPH.CUST_NO
+		         ), '%Y%m%d%H%i%S') AS EXP_CMP_DT
+		FROM    TB_CUSTOMER C
+		INNER JOIN
+		        TB_CUST_POINT_HST CPH
+		ON      C.CUST_NO = CPH.CUST_NO
+		WHERE   C.CUST_NO = #{custNo}
+		ORDER BY CPH.REG_DT DESC
 	</select>
 
 	<!-- 회원 상품권이력 -->

+ 53 - 0
src/main/java/com/style24/persistence/mybatis/shop/TsaMorebetter.xml

@@ -608,5 +608,58 @@
 			, UPD_DT = NOW()
 		WHERE TMTB_SQ = #{tmtbSq}
 	</update>
+
+	<delete id="deleteTmtbApplyGoodsTemp" parameterType="MoreBetterGoods">
+		/* TsaMarketing.deleteTmtbApplyGoodsTemp */
+		DELETE FROM TB_TMTB_APPLY_GOODS_TEMP
+		WHERE	REG_NO = #{regNo}
+	</delete>
+
+	<insert id="createTmtbApplyGoodsTemp" parameterType="MoreBetterGoods">
+		/* TsaMarketing.createTmtbApplyGoodsTemp */
+		INSERT INTO TB_TMTB_APPLY_GOODS_TEMP(
+											 REG_NO
+											,GOODS_CD
+		)
+		VALUES (
+				   #{regNo}
+			   ,#{goodsCd}
+			   )
+	</insert>
+
+	<select id="getMorebetterRealApplyGoodsList" parameterType="MoreBetter" resultType="MoreBetterGoods">
+		/* TsaMarketing.getMorebetterRealApplyGoodsList */
+		SELECT	GOODS_CD
+		  FROM	TB_TMTB_APPLY_GOODS_TEMP
+		 WHERE	1=1
+		   AND	REG_NO = #{regNo}
+		   AND	GOODS_CD NOT IN (
+							SELECT	GOODS_CD
+							FROM	TB_TMTB_USING_GOODS_TEMP
+							WHERE	1=1
+							  AND	REG_NO = #{regNo}
+							)
+	</select>
+
+	<select id="getMorebetterCompBrandGoodsList" parameterType="MoreBetterGoods" resultType="MoreBetterGoods">
+		/* TsaMarketing.getMorebetterCompBrandGoodsList */
+		SELECT  G.GOODS_CD
+				,'G800_20' AS GOODS_GB
+				,'G260_10' AS TARGET_GB
+		FROM  TB_GOODS G
+		WHERE  1=1
+		<if test="multiSupplyCompCd != null and multiSupplyCompCd.length>0">
+			AND G.SUPPLY_COMP_CD IN
+			<foreach collection="multiSupplyCompCd" item="item" index="index"  open="(" close=")" separator=",">
+				#{item}
+			</foreach>
+		</if>
+		<if test="multiBrand != null and multiBrand.length>0">
+			AND G.BRAND_CD IN
+			<foreach collection="multiBrand" item="item" index="index"  open="(" close=")" separator=",">
+				#{item}
+			</foreach>
+		</if>
+	</select>
 	<!--// CSB 진행 -->
 </mapper>

+ 489 - 0
src/main/java/com/style24/persistence/mybatis/shop/TsaPg.xml

@@ -2,7 +2,496 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.style24.admin.biz.dao.TsaPgDao">
 
+	<!-- 주문 샘플 데이터 (추후 삭제 예정) -->
+	<select id="getOrderSampleGoodsInfo" parameterType="Goods" resultType="Goods">
+		SELECT SYS_IMG_NM
+		     , GOODS_CD
+		     , GOODS_NM
+		     , STOCK_QTY_SUM
+		     , GOODS_STAT
+		     , STYLE_YEAR
+			 , SEASON_CD
+		     , LIST_PRICE
+		     , CURR_PRICE
+		     , PRICE_UPD_DT
+		     , ERP_STOCK_LINK_YN
+		     , FORMAL_GB
+		     , RETURNABLE_YN
+		     , REG_DT
+		     , REG_NM
+			 , UPD_DT
+		     , UPD_NM
+		     , REP_GOODS_CD
+			 , GROUP_CONCAT(OPT_CD2 ORDER BY DISP_ORD DESC, OPT_CD2 SEPARATOR ',')        AS SITE_CD
+		  FROM (
+			  SELECT GI.SYS_IMG_NM
+				   , G.GOODS_CD
+				   , G.GOODS_NM
+				   , (CASE WHEN G.GOODS_TYPE = 'G056_N' THEN (SELECT IFNULL(SUM(CURR_STOCK_QTY - BASE_STOCK_QTY),0) FROM VW_STOCK WHERE GOODS_CD = G.GOODS_CD)
+						   ELSE (SELECT IFNULL(SUM(CURR_STOCK_QTY - BASE_STOCK_QTY),0) FROM VW_STOCK_COMPOSE WHERE GOODS_CD = G.GOODS_CD)
+					  END) AS STOCK_QTY_SUM
+				   , G.GOODS_STAT
+				   , G.STYLE_YEAR
+				   , G.SEASON_CD
+				   , G.LIST_PRICE
+				   , G.CURR_PRICE
+				   , G.PRICE_UPD_DT
+				   , G.ERP_STOCK_LINK_YN
+				   , G.FORMAL_GB
+				   , G.RETURNABLE_YN
+				   , G.REG_DT
+				   , FN_GET_USER_NM(G.REG_NO) AS REG_NM
+				   , G.UPD_DT
+				   , FN_GET_USER_NM(G.UPD_NO) AS UPD_NM
+				   , IFNULL(GC.COMPS_GOODS_CD, G.GOODS_CD) AS REP_GOODS_CD
+				   , OP.OPT_CD2
+				   , OP.DISP_ORD
+				FROM TB_GOODS G
+				LEFT OUTER JOIN TB_GOODS_COMPOSE GC
+				  ON G.GOODS_CD = GC.GOODS_CD
+			   INNER JOIN TB_OPTION OP
+				  ON IFNULL(GC.COMPS_GOODS_CD, G.GOODS_CD) = OP.GOODS_CD
+				LEFT OUTER JOIN TB_GOODS_IMG GI
+				  ON G.GOODS_CD = GI.GOODS_CD
+			   INNER JOIN TB_BRAND B
+				  ON G.BRAND_CD = B.BRAND_CD
+			   WHERE G.GOODS_CD IN
+		<foreach collection="arrGoodsCd" item="item" index="index"  open="(" close=")" separator=",">
+			#{item}
+		</foreach>
+		  ) Z
+		 GROUP BY SYS_IMG_NM, GOODS_CD, GOODS_NM, STOCK_QTY_SUM, GOODS_STAT, STYLE_YEAR
+				, SEASON_CD, LIST_PRICE, CURR_PRICE, PRICE_UPD_DT, ERP_STOCK_LINK_YN, FORMAL_GB, RETURNABLE_YN, REG_DT, REG_NM
+				, UPD_DT, UPD_NM, REP_GOODS_CD
+	</select>
 	
+	<select id="getOrderSampleGoodsStock" parameterType="Goods" resultType="Goods">
+		SELECT GOODS_CD
+		     , OPT_CD2 AS SITE_CD
+		     , MAX(CURR_STOCK_QTY - BASE_STOCK_QTY) AS MIN_ORD_QTY
+		  FROM VW_STOCK
+		 WHERE GOODS_CD = #{goodsCd}
+		   AND OPT_CD2 = #{siteCd}
+		 GROUP BY GOODS_CD, OPT_CD2
+	</select>
+	
+	<insert id="createOrderSample" parameterType="OrderSample" keyProperty="ordNo">
+		INSERT INTO TB_ORDER
+			( MALL_GB
+			, ORD_DT
+			, PAY_DT
+			, CUST_NO
+			, ORD_NM
+			, ORD_PHNNO
+			, ORD_TELNO
+			, ORD_EMAIL
+			, SITE_CD
+			, NPAY_ORD_NO
+			, FRONT_GB
+			, REG_NO
+			, REG_DT
+			, UPD_NO
+			, UPD_DT
+			)
+		VALUES
+			( 'G011_10'			-- MALL_GB
+			, NOW()				-- ORD_DT
+			, NOW()				-- PAY_DT
+			, #{custNo}			-- CUST_NO
+			, #{ordNm}			-- ORD_NM
+			, #{ordPhnno}		-- ORD_PHNNO
+			, NULL				-- ORD_TELNO
+			, #{ordEmail}		-- ORD_EMAIL
+			, 'G000_10'			-- SITE_CD
+			, 0					-- NPAY_ORD_NO
+			, 'P'				-- FRONT_GB
+			, #{custNo}			-- REG_NO
+			, NOW()				-- REG_DT
+			, #{custNo}			-- UPD_NO
+			, NOW()				-- UPD_DT
+			)
+	</insert>
+	
+	<insert id="createDelveryAddrSample" parameterType="OrderSample" keyProperty="delvAddrSq">
+		INSERT INTO TB_DELIVERY_ADDR
+			( RECIP_NM
+			, RECIP_PHNNO
+			, RECIP_TELNO
+			, RECIP_ZIPCODE
+			, RECIP_BASE_ADDR
+			, RECIP_DTL_ADDR
+			, DELV_MEMO
+			, REG_NO
+			, REG_DT
+			, UPD_NO
+			, UPD_DT
+			)
+		VALUES
+			( #{ordNm}				-- RECIP_NM
+			, #{ordPhnno}			-- RECIP_PHNNO
+			, NULL					-- RECIP_TELNO
+			, #{recipZipcode}		-- RECIP_ZIP_NO
+			, #{recipBaseAddr}		-- RECIP_BASE_ADDR
+			, #{recipDtlAddr}		-- RECIP_DTL_ADDR
+			, '배송메모'				-- DELV_MEMO
+			, #{custNo}				-- REG_NO
+			, NOW()					-- REG_DT
+			, #{custNo}				-- UPD_NO
+			, NOW()					-- UPD_DT
+			)
+	</insert>
+	
+	<insert id="createDeliveryFeeSample" parameterType="OrderSample" keyProperty="delvFeeSq">
+		INSERT INTO TB_DELIVERY_FEE
+			( PAY_SQ
+			, ORD_NO
+			, DELV_FEE_GB
+			, DELV_FEE_CD
+			, DELV_FEE
+			, DELV_CPN_SQ
+			, DELV_CPN_DC_AMT
+			, REAL_DELV_AMT
+			, ORD_CHG_SQ
+			, SUPPLY_COMP_CD
+			, DELV_USAC_YN
+			, DELV_USAC_DT
+			, REG_NO
+			, REG_DT
+			, UPD_NO
+			, UPD_DT
+			)
+		SELECT 0               -- PAY_SQ
+			 , #{ordNo}        -- ORD_NO
+			 , #{delvFeeGb}    -- DELV_FEE_GB
+			 , G.DELV_FEE_CD   -- DELV_FEE_CD
+			 , 0               -- DELV_FEE
+			 , NULL            -- DELV_CPN_SQ
+			 , 0               -- DELV_CPN_DC_AMT
+			 , 0               -- REAL_DELV_AMT
+			 , NULL            -- ORD_CHG_SQ
+			 , G.SUPPLY_COMP_CD -- SUPPLY_COMP_CD
+			 , 'N'             -- DELV_USAC_YN
+			 , NULL            -- DELV_USER_DT
+			 , #{custNo}       -- REG_NO
+			 , NOW()           -- REG_DT
+			 , #{custNo}       -- UPD_NO
+			 , NOW()           -- UPO_DT
+		  FROM TB_GOODS G
+		 INNER JOIN TB_DELV_FEE_POLICY DFP
+		    ON G.DELV_FEE_CD = DFP.DELV_FEE_CD
+		 WHERE G.GOODS_CD = #{goodsCd}
+		   AND NOT EXISTS(SELECT 1
+							FROM TB_DELIVERY_FEE
+						   WHERE ORD_NO <![CDATA[<>]]> #{ordNo}
+							 AND DELV_FEE_GB <![CDATA[<>]]> #{delvFeeGb}
+							 AND DELV_FEE_CD <![CDATA[<>]]> G.DELV_FEE_CD)
+	</insert>
+	
+	<insert id="createOrderDetailSample" parameterType="OrderSample" keyProperty="ordDtlNo">
+		INSERT INTO TB_ORDER_DETAIL
+			( ORD_NO
+			, ORD_EXCH_GB
+			, ORD_DTL_STAT
+			, ORG_ORD_DTL_NO
+			, SUPPLY_COMP_CD
+			, GOODS_CD
+			, PRODUCT_NO
+			, PRODUCT_CODE
+			, FORMAL_GB
+			, GOODS_TYPE
+			, LIST_PRICE
+			, CURR_PRICE
+			, DC_RATE
+			, OPT_ADD_PRICE
+			, ORD_QTY
+			, ORD_AMT
+			, CNCL_RTN_QTY
+			, CNCL_RTN_AMT
+			, CPN1_CPN_SQ
+			, CPN1_DC_AMT
+			, TMTB1_SQ
+			, TMTB1_DC_AMT
+			, TMTB2_SQ
+			, TMTB2_DC_AMT
+			, GOODS_CPN_SQ
+			, GOODS_CPN_DC_AMT
+			, CART_CPN_SQ
+			, CART_CPN_DC_AMT
+			, BURDEN_RATE
+			, PNT_DC_AMT
+			, PRE_PNT_DC_AMT
+			, SAVE_PNT_AMT
+			, REAL_ORD_AMT
+			, GFCD_USE_AMT
+			, VENDOR_ID
+			, EXTMALL_ID
+			, AGENT_ORDER_ID
+			, EXTMALL_ORDER_ID
+			, CHANGABLE_YN
+			, CHANGE_FEE_FREE_YN
+			, RETURNABLE_YN
+			, RETURN_FEE_FREE_YN
+			, SOLDOUT_YN
+			, SOLDOUT_MEMO
+			, SOLDOUT_REG_NO
+			, SOLDOUT_REG_DT
+			, DELV_ADDR_SQ
+			, DELV_FEE_CD
+			, SHOT_DELV_YN
+			, GIFT_PACK_YN
+			, MAKE_GOODS_YN
+			, ENTRY_NO
+			, DELV_LOC_CD
+			, DELV_ASSIGN_DT
+			, DELV_ASSIGN_STAT
+			, DSTRBT_NOTE
+			, DELV_STDT
+			, DELV_EDDT
+			, SHIP_COMP_CD
+			, INVOICE_NO
+			, INVOICE_SEND_YN
+			, SELL_STORE_CD
+			, SELL_FEE_RATE
+			, AF_LINK_CD
+			, ITHR_CD
+			, CONTENTS_LOC
+			, PLAN_DTL_SQ
+			, SOCIAL_SQ
+			, REG_NO
+			, REG_DT
+			, UPD_NO
+			, UPD_DT
+			)
+		SELECT #{ordNo} -- ORD_NO
+			, 'O' -- ORD_EXCH_GB
+			, #{ordDtlStat} -- ORD_DTL_STAT
+			, NULL -- ORG_ORD_DTL_NO
+			, G.SUPPLY_COMP_CD -- SUPPLY_COMP_CD
+			, G.GOODS_CD -- GOODS_CD
+			, G.PRODUCT_NO -- PRODUCT_NO
+			, G.PRODUCT_CODE -- PRODUCT_CODE
+			, G.FORMAL_GB -- FORMAL_GB
+			, G.GOODS_TYPE -- GOODS_TYPE
+			, G.LIST_PRICE -- LIST_PRICE
+			, G.CURR_PRICE -- CURR_PRICE
+			, G.DC_RATE -- DC_RATE
+			, 0 -- OPT_ADD_PRICE
+			, #{ordQty} -- ORD_QTY
+			, #{ordQty} * G.CURR_PRICE -- ORD_AMT
+			, 0 -- CNCL_RTN_QTY
+			, 0 -- CNCL_RTN_AMT
+			, 0 -- CPN1_CPN_SQ
+			, 0 -- CPN1_DC_AMT
+			, 0 -- TMTB1_SQ
+			, 0 -- TMTB1_DC_AMT
+			, 0 -- TMTB2_SQ
+			, 0 -- TMTB2_DC_AMT
+			, 0 -- GOODS_CPN_SQ
+			, 0 -- GOODS_CPN_DC_AMT
+			, 0 -- CART_CPN_SQ
+			, 0 -- CART_CPN_DC_AMT
+			, 0 -- BURDEN_RATE
+			, 0 -- PNT_DC_AMT
+			, 0 -- PRE_PNT_DC_AMT
+			, 0 -- SAVE_PNT_AMT
+			, #{ordQty} * G.CURR_PRICE -- REAL_ORD_AMT
+			, 0 -- GFCD_USE_AMT
+			, '' -- VENDOR_ID
+			, '' -- EXTMALL_ID
+			, '' -- AGENT_ORDER_ID
+			, '' -- EXTMALL_ORDER_ID
+			, 'Y' -- CHANGABLE_YN
+			, 'Y' -- CHANGE_FEE_FREE_YN
+			, 'Y' -- RETURNABLE_YN
+			, 'Y' -- RETURN_FEE_FREE_YN
+			, 'N' -- SOLDOUT_YN
+			, '' -- SOLDOUT_MEMO
+			, NULL -- SOLDOUT_REG_NO
+			, NOW() -- SOLDOUT_REG_DT
+			, #{delvAddrSq} -- DELV_ADDR_SQ
+			, G.DELV_FEE_CD -- DELV_FEE_CD
+			, 'N' -- SHOT_DELV_YN
+			, 'N' -- GIFT_PACK_YN
+			, 'N' -- MAKE_GOODS_YN
+			, '' -- ENTRY_NO
+			, '' -- DELV_LOC_CD
+			, NOW() -- DELV_ASSIGN_DT
+			, '' -- DELV_ASSIGN_STAT
+			, '' -- DSTRBT_NOTE
+			, NOW() -- DELV_STDT
+			, NOW() -- DELV_EDDT
+			, 'S0001' -- SHIP_COMP_CD
+			, '' -- INVOICE_NO
+			, '' -- INVOICE_SEND_YN
+			, '' -- SELL_STORE_CD
+			, 0 -- SELL_FEE_RATE
+			, '' -- AF_LINK_CD
+			, '' -- ITHR_CD
+			, '' -- CONTENTS_LOC
+			, NULL -- PLAN_DTL_SQ
+			, NULL -- SOCIAL_SQ
+			, #{custNo} -- REG_NO
+			, NOW() -- REG_DT
+			, #{custNo} -- UPD_NO
+			, NOW() -- UPD_DT
+			FROM TB_GOODS G
+		 WHERE G.GOODS_CD = #{goodsCd}
+		   AND NOT EXISTS (SELECT 1 FROM TB_ORDER_DETAIL WHERE ORD_NO = #{ordNo} AND GOODS_CD = #{goodsCd})
+	</insert>
+	
+	<insert id="createOrderDetailItemSample" parameterType="OrderSample" keyProperty="">
+		INSERT INTO TB_ORDER_DETAIL_ITEM
+			( ORD_DTL_NO
+			, ORD_NO
+			, ORD_DTL_STAT
+			, ITEM_CD
+			, OPT_CD
+			, OPT_CD1
+			, OPT_CD2
+			, SKU_MODEL_NO
+			, PRODUCT_NO
+			, PRODUCT_CODE
+			, ITEM_QTY
+			, ITEM_PRICE
+			, OPT_ADD_PRICE
+			, DISP_ORD
+			, ORD_AMT
+			, CNCL_RTN_AMT
+			, CPN1_DC_AMT
+			, TMTB1_DC_AMT
+			, TMTB2_DC_AMT
+			, GOODS_CPN_DC_AMT
+			, CART_CPN_DC_AMT
+			, PNT_DC_AMT
+			, PRE_PNT_DC_AMT
+			, SAVE_PNT_AMT
+			, REAL_ORD_AMT
+			, GFCD_USE_AMT
+			, REG_NO
+			, REG_DT
+			, UPD_NO
+			, UPD_DT
+			)
+		SELECT OD.ORD_DTL_NO       -- ORD_DTL_NO
+			 , OD.ORD_NO           -- ORD_NO
+			 , OD.ORD_DTL_STAT     -- ORD_DTL_STAT
+			 , G.GOODS_CD         -- ITEM_CD
+			 , OP.OPT_CD          -- OPT_CD
+			 , OP.OPT_CD1         -- OPT_CD1
+			 , OP.OPT_CD2         -- OPT_CD2
+			 , OP.SKU_MODEL_NO    -- SKU_MODEL_NO
+			 , OP.PRODUCT_NO      -- PRODUCT_NO
+			 , OP.PRODUCT_CODE    -- PRODUCT_CODE
+			 , IFNULL(GC.QTY, 1)  -- ITEM_QTY
+			 , IFNULL(GC.COMPS_CURR_PRICE, G.CURR_PRICE)       -- ITEM_PRICE
+			 , 0                  -- OPT_ADD_PRICE
+			 , IFNULL(GC.DISP_ORD, 1)                  -- DISP_ORD
+			 , #{ordQty} * IFNULL(GC.COMPS_CURR_PRICE, G.CURR_PRICE)          -- ORD_AMT
+			 , 0     -- CNCL_RTN_AMT
+			 , 0      -- CPN1_DC_AMT
+			 , 0     -- TMTB1_DC_AMT
+			 , 0     -- TMTB2_DC_AMT
+			 , 0 -- GOODS_CPN_DC_AMT
+			 , 0  -- CART_CPN_DC_AMT
+			 , 0       -- PNT_DC_AMT
+			 , 0   -- PRE_PNT_DC_AMT
+			 , 0     -- SAVE_PNT_AMT
+			 , #{ordQty} * IFNULL(GC.COMPS_CURR_PRICE, G.CURR_PRICE)     -- REAL_ORD_AMT
+			 , 0     -- GFCD_USE_AMT
+			 , #{custNo}          -- REG_NO
+			 , NOW()              -- REG_DT
+			 , #{custNo}          -- UPD_NO
+			 , NOW()              -- UPD_DT
+		  FROM TB_ORDER_DETAIL OD
+		 INNER JOIN TB_GOODS                     G
+		    ON OD.GOODS_CD = G.GOODS_CD
+		  LEFT OUTER JOIN TB_GOODS_COMPOSE GC
+		    ON G.GOODS_CD = GC.GOODS_CD
+		   AND GC.COMPS_GOODS_CD = #{compsGoodsCd}
+		 INNER JOIN TB_OPTION                    OP
+		    ON IFNULL(GC.COMPS_GOODS_CD, G.GOODS_CD) = OP.GOODS_CD
+		   AND OP.OPT_CD2 = #{optCd}
+		 WHERE OD.ORD_DTL_NO = #{ordDtlNo}
+	</insert>
+	
+	<insert id="createPaymentSample" parameterType="OrderSample" keyProperty="paySq">
+		INSERT INTO TB_PAYMENT
+			( ORD_NO
+			, PAY_DT
+			, PAY_MEANS
+			, PAY_AMT
+			, PG_CPN_AMT
+			, NPAY_PNT_AMT
+			, PAY_GB
+			, PAY_STAT
+			, PG_GB
+			, PG_TID
+			, PG_TRADE_NO
+			, PG_SHOP_ID
+			, CARD_TYPE
+			, CARD_KIND
+			, CARD_BANK
+			, CARD_NM
+			, CARD_MIPS
+			, CARD_PCABLE_YN
+			, VA_NO
+			, VA_NM
+			, VA_BANK
+			, VA_DEADLINE
+			, TELECOM
+			, ESCROW_YN
+			, ORD_CHG_SQ
+			, REG_NO
+			, REG_DT
+			, UPD_NO
+			, UPD_DT
+			)
+		SELECT OD.ORD_NO   -- ORD_NO
+			 , NOW()      -- PAY_DT
+			 , 'G014_30'  -- PAY_MEANS
+			 , SUM(OD.REAL_ORD_AMT + DF.REAL_DELV_AMT)  -- PAY_AMT
+			 , 0          -- PG_CPN_AMT
+			 , 0          -- NPAY_CPN_AMT
+			 , 'O'        -- PAY_GB
+			 , 'G016_30'  -- PAY_STAT
+			 , 'KCP'      -- PG_GB
+			 , 'TID00001' -- PG_TID
+			 , '101010'   -- PG_TRADE_NO
+			 , 'STYLE24'  -- PG_SHOP_ID
+			 , 'Y'        -- CARD_TYPE
+			 , ''         -- CARD_KIND
+			 , ''         -- CARD_BANK
+			 , '신한카드'     -- CARD_NM
+			 , ''         -- CARD_MIPS
+			 , ''         -- CARD_PCABLE_YN
+			 , ''         -- VA_NO
+			 , ''         -- VA_NM
+			 , ''         -- VA_BANK
+			 , NOW()      -- VA_DEADLINE
+			 , ''         -- TELECOM
+			 , ''         -- ESCROW_YN
+			 , NULL       -- ORD_CHG_SQ
+			 , #{custNo}          -- REG_NO
+			 , NOW()      -- REG_DT
+			 , #{custNo}          -- UPD_NO
+			 , NOW()      -- UPD_DT
+		  FROM TB_ORDER_DETAIL OD
+		 INNER JOIN (SELECT ORD_NO
+						  , SUM(REAL_DELV_AMT) AS REAL_DELV_AMT
+					   FROM TB_DELIVERY_FEE
+					  WHERE ORD_NO = #{ordNo}
+					  GROUP BY ORD_NO) DF
+		    ON OD.ORD_NO = DF.ORD_NO
+		 WHERE OD.ORD_NO = #{ordNo}
+		 GROUP BY OD.ORD_NO
+	</insert>
+	
+	<update id="updateDeliveryFeeSample" parameterType="OrderSample">
+		UPDATE TB_DELIVERY_FEE
+		   SET PAY_SQ = #{paySq}
+		 WHERE ORD_NO = #{ordNo}
+	</update>
+	<!-- //주문 샘플 데이터 (추후 삭제 예정) -->
 	
 </mapper>
 

+ 2 - 3
src/main/webapp/WEB-INF/views/customer/CellphoneChangePopupForm.html

@@ -18,7 +18,7 @@
 	<div class="panelStyle">
 		<!-- TITLE -->
 		<div class="panelTitle">
-			<strong >휴대전화번호변경팝업</strong>
+			<strong >휴대전화 번호 변경팝업</strong>
 			<button type="button" class="close" onclick="uifnPopupClose('popupCellphoneForm')"><em class="fa fa-times"></em></button>
 		</div>
 		<!-- //TITLE -->
@@ -59,7 +59,7 @@
 			<ul class="panelBar">
 				<li class="right">
 					<button type="button" id="btnSendCustCrtfdNo" class="btn btn-success btn-lg" >인증번호발송</button>
-					<button type="button" id="btnCustCertNo" class="btn btn-success btn-lg" style="display: none">인증번호확인</button>
+					<button type="button" id="btnCustCertNo" class="btn btn-success btn-lg" style="display: none">확인(번호변경)</button>
 				</li>
 			</ul>
 		</div>
@@ -71,7 +71,6 @@
 	const elementCellPhnno = [[${elementCellPhnno}]];
 	const elementCustNo = [[${elementCustNo}]];
 
-
 	// 인증번호 전송
 	$('#btnSendCustCrtfdNo').on('click', function () {
 		//휴대폰번호

+ 23 - 32
src/main/webapp/WEB-INF/views/customer/CustomerDetailForm.html

@@ -96,14 +96,14 @@
 										<td class="dashR">
 											<select id="custGb" name="custGb">
 												<option th:if="${custGbList}" th:each="oneData, status : ${custGbList}" th:value="${oneData.cd}"
-														th:text="|${oneData.cdNm}|"></option>
+														th:text="${'[' + oneData.cd + '] '+oneData.cdNm}"></option>
 											</select>
 										</td>
 										<th class="dashR">회원등급<em class="required" title="필수"></em></th>
 										<td class="dashR">
 											<select id="custGrade" name="custGrade">
 												<option th:if="${custGradeList}" th:each="oneData, status : ${custGradeList}" th:value="${oneData.cd}"
-														th:text="|${oneData.cdNm}|"></option>
+														th:text="${'[' + oneData.cd + '] '+oneData.cdNm}"></option>
 											</select>
 										</td>
 									</tr>
@@ -113,7 +113,7 @@
 											<select id="managedRsn" name="managedRsn">
 												<option value="">일반</option>
 												<option th:if="${managedRsnList}" th:each="oneData, status : ${managedRsnList}" th:value="${oneData.cd}"
-														th:text="|${oneData.cdNm}|"></option>
+														th:text="${'[' + oneData.cd + '] '+oneData.cdNm}"></option>
 											</select>
 											<span class="infoTxt cRed h5" id="managedRsnDp" name="managedRsnDp"></span>
 										</td>
@@ -158,16 +158,7 @@
 									<tr>
 										<th class="dashR">휴대전화번호<em class="required" title="필수"></em></th>
 										<td class="dashR">
-											<input type="hidden" name="cellPhnno" data-valid-name="휴대전화"/>
-											<select id="firstNo" name="firstNo">
-												<option value="">선택</option>
-												<option th:if="${nationalHpNumberList}" th:each="oneData, status : ${nationalHpNumberList}"
-														th:value="${oneData.cd}" th:text="|${oneData.cd}|"></option>
-											</select> -
-											<input type="text" id="middleNo" name="middleNo" class="w50" maxlength="4" required="required"
-												   data-valid-type="numeric" data-valid-name="휴대전화번호"/> -
-											<input type="text" id="lastNo" name="lastNo" class="w50" maxlength="4" required="required"
-												   data-valid-type="numeric" data-valid-name="휴대전화번호"/>
+											<input type="text" name="cellPhnno" class="w130" readonly="readonly"/>
 											<button type="button" id="btnCustSendLms" class="btn btn-info btn-lg">LMS전송</button>
 											<button type="button" id="btnCustCrtfd" class="btn btn-info btn-lg">번호변경</button>
 										</td>
@@ -181,9 +172,9 @@
 										<th class="dashR">이메일<em class="required" title="필수"></em></th>
 										<td class="dashR">
 											<input type="hidden" name="email" data-valid-name="이메일"/>
-											<input type="text" id="emailId" name="emailId" class="w300"/>
+											<input type="text" id="emailId" name="emailId" class="w200" maxlength="30"/>
 											@
-											<input type="text" id="emailDomain" name="emailDomain" class="w150"/>
+											<input type="text" id="emailDomain" name="emailDomain" class="w150" maxlength="20"/>
 											<select id="emailDomainList" name="emailDomainList">
 												<option value="">선택하세요</option>
 												<option th:if="${emailDomainList}" th:each="oneData, status : ${emailDomainList}" th:value="${oneData.cd}"
@@ -644,7 +635,7 @@
 
 	//쿠폰내역 그리드
 	const columnCouponDefs = [
-		{width: 40, minWidth: 40, cellClass: 'text-center', pinned: 'left', headerCheckboxSelection: true, checkboxSelection: true, filter: false},
+		// {width: 40, minWidth: 40, cellClass: 'text-center', pinned: 'left', headerCheckboxSelection: true, checkboxSelection: true, filter: false},
 		{headerName: "회원쿠폰SQ", field: "custCpnSq", width: 100, cellClass: 'text-center', hide: true},
 		{headerName: "쿠폰ID", field: "cpnId", width: 100, cellClass: 'text-center'},
 		{headerName: "쿠폰명", field: "cpnNm", width: 300, cellClass: 'text-center'},
@@ -674,7 +665,8 @@
 			}
 		},
 		{headerName: "쿠폰발행 상세사유", field: "pubReasonDtl", width: 300, cellClass: 'text-center'},
-		{headerName: "등록자", field: "regNo", width: 100, cellClass: 'text-center'},
+		{headerName: "만료알림발송여부", field: "endAlimSendYn", width: 150, cellClass: 'text-center'},
+		{headerName: "등록자", field: "regNm", width: 100, cellClass: 'text-center'},
 		{
 			headerName: "등록일시", field: "regDt", width: 150, cellClass: 'text-center',
 			cellRenderer: function (params) {
@@ -892,7 +884,16 @@
 	let gridAddrOptions = gagaAgGrid.getGridOptions(columnAddrDefs);		//주소정보 그리드
 	let gridContactOptions = gagaAgGrid.getGridOptions(columnContactDefs);	//회원접촉이력 그리드
 
-	gridCouponOptions.rowSelection = 'multiple';
+	gridOrderOptions.suppressRowClickSelection = true;
+	gridCounselOptions.suppressRowClickSelection = true;
+	gridGoodsQnaOptions.suppressRowClickSelection = true;
+	gridCouponOptions.suppressRowClickSelection = true;
+	gridPointOptions.suppressRowClickSelection = true;
+	gridGiftCardOptions.suppressRowClickSelection = true;
+	gridReviewOptions.suppressRowClickSelection = true;
+	gridGradeOptions.suppressRowClickSelection = true;
+	gridAddrOptions.suppressRowClickSelection = true;
+	gridContactOptions.suppressRowClickSelection = true;
 
 	// 기본정보 - 비밀번호 초기화 버튼
 	$('#btnResetPassword').on('click', function () {
@@ -1098,7 +1099,9 @@
 
 	// 쿠폰발급 버튼
 	$('#btnCustCouponCreate').on('click', function () {
-		cfnCpnPubForCustPopup();
+		let elementCustNo ='#custInfoForm input[name=custNo]';
+		const actionUrl = '/marketing/coupon/issue/popup/form?elementCustNo=' + encodeURIComponent(elementCustNo);
+		cfnOpenModalPopup(actionUrl, 'popupCouponIssue');
 	});
 
 
@@ -1332,13 +1335,6 @@
 	// 휴대전화 유효성 체크 및 데이터 셋팅
 	var fnCheckValidationPhnno = function (formId) {
 		let result = true;
-
-		let firstNo = $(formId + ' select[name=firstNo]').val();
-		let middleNo = $(formId + ' input[name=middleNo]').val();
-		let lastNo = $(formId + ' input[name=lastNo]').val();
-		let cellPhnno = firstNo + '-' + middleNo + '-' + lastNo;
-		$(formId + ' input[name=cellPhnno]').val(cellPhnno);
-
 		if (!gagajf.testRegexp($(formId + ' input[name=cellPhnno]'), /^(01(?:0|1|[6-9])-(?:\d{3}|\d{4})-\d{4})$/)) {
 			result = false;
 		}
@@ -1391,12 +1387,7 @@
 
 	// 휴대전화번호
 	var fnDisplayCellPhnno = function (cellPhnno) {
-		if (!gagajf.isNull(cellPhnno)) {
-			let cellPhSplit = cellPhnno.split("-");
-			$('#firstNo').val(cellPhSplit[0]);
-			$('#middleNo').val(cellPhSplit[1]);
-			$('#lastNo').val(cellPhSplit[2]);
-		}
+		$('#custInfoForm input[name=cellPhnno]').val(cellPhnno);
 	};
 
 	// 이메일

+ 336 - 0
src/main/webapp/WEB-INF/views/marketing/CouponIssuePopupForm.html

@@ -0,0 +1,336 @@
+<!DOCTYPE html>
+<html lang="ko"
+	xmlns:th="http://www.thymeleaf.org">
+<!--
+ *******************************************************************************
+ * @source  : CouponIssuePopupForm.html
+ * @desc    : 쿠폰발급 팝업 Page
+ *============================================================================
+ * STYLE24
+ * Copyright(C) 2020 TSIT, All rights reserved.
+ *============================================================================
+ * VER  DATE         AUTHOR      DESCRIPTION
+ * ===  ===========  ==========  =============================================
+ * 1.0  2021.01.28   jsshin     최초 작성
+ *******************************************************************************
+ -->
+<div class="modalPopup" data-width="960" data-height="900" >
+	<div id="panel" class="panelStyle">
+		<!-- TITLE -->
+		<div class="panelTitle">
+			<strong>쿠폰 발급</strong>
+			<button type="button" class="close" onclick="uifnPopupClose('popupCouponIssue');"><em class="fa fa-times"></em></button>
+		</div>
+		<!-- //TITLE -->
+
+		<!-- CONTENT -->
+		<div class="panelContent">
+			<form id="searchCouponForm" name="searchCouponForm" action="#" th:action="@{'/marketing/coupon/retrieve/list'}" th:method="post">
+				<table class="frmStyle" aria-describedby="검색조건">
+					<colgroup>
+						<col style="width:10%;"/>
+						<col style="width:40%;"/>
+						<col style="width:10%;"/>
+						<col style="width:40%;"/>
+					</colgroup>
+					<tbody>
+						<tr>
+							<th>사이트<em class="required" title="필수"></em></th>
+							<td>
+								<select name="siteCd" required="required">
+									<option th:if="${siteList}" th:each="oneData, status : ${siteList}" th:value="${oneData.cd}" th:text="|[${oneData.cd}] ${oneData.cdNm}|"></option>
+								</select>
+							</td>
+							<th>쿠폰유형</th>
+							<td>
+								<select name="cpnType">
+									<option value="">[전체]</option>
+									<option th:if="${cpnTypeList}" th:each="oneData, status : ${cpnTypeList}" th:value="${oneData.cd}" th:text="|[${oneData.cd}] ${oneData.cdNm}|"></option>
+								</select>
+							</td>
+						</tr>
+						<tr>
+							<th>쿠폰ID</th>
+							<td>
+								<input type="text" name="cpnId" maxlength="20"/>
+							</td>
+							<th>쿠폰명</th>
+							<td>
+								<input type="text" name="cpnNm" maxlength="50"/>
+							</td>
+						</tr>
+					</tbody>
+				</table>
+				<ul class="panelBar">
+					<li class="center">
+						<button type="button" class="btn btn-base btn-lg" id="btnSearchCouponRetrieve">조회</button>
+					</li>
+				</ul>
+			</form>
+			<!-- 리스트 영역 -->
+			<div id="gridCouponList" style="width: 100%; height: 420px;" class="ag-theme-balham"></div>
+			<!-- //리스트 영역 -->
+			<form id="couponIssueForm" name="couponIssueForm">
+				<input type="hidden" name="cpnId"/>
+				<input type="hidden" name="pdGb"/>
+				<input type="hidden" name="custNo"/>
+				<table class="frmStyle" aria-describedby="발급내용">
+					<colgroup>
+						<col style="width: 10%"/>
+						<col style="width: 40%"/>
+						<col style="width: 10%"/>
+						<col style="width: 40%"/>
+					</colgroup>
+					<tr id="availTermsTr">
+						<th class="availTerm">유효기간시작일시<em class="required" title="필수"></em></th>
+						<td class="availTerm">
+							<input type="text" name="availStdt" class="schDate w100" data-valid-name="유효기간시작일시"/>
+							<select name="availStHH" data-valid-name="유효기간시작(시)"required="required">
+								<th:block th:each="num, index : ${#numbers.sequence(0, 23)}">
+									<option th:value="${#numbers.formatInteger(num, 2)}" th:text="|${#numbers.formatInteger(num, 2)}시|">시간</option>
+								</th:block>
+							</select>
+							<select name="availStMM" data-valid-name="유효기간시작(분)" required="required">
+								<th:block th:each="num, index : ${#numbers.sequence(0, 59)}">
+									<option th:value="${#numbers.formatInteger(num, 2)}" th:text="|${#numbers.formatInteger(num, 2)}분|">분</option>
+								</th:block>
+							</select>
+						</td>
+
+						<th class="availTerm">유효기간종료일시<em class="required" title="필수"></em></th>
+						<td class="availTerm">
+							<input type="text" name="availEddt" class="schDate w100" data-valid-name="유효기간종료일시"/>
+							<select name="availEdHH" data-valid-name="유효기간종료(시)">
+								<th:block th:each="num, index  : ${#numbers.sequence(0, 23)}">
+									<option th:value="${#numbers.formatInteger(num, 2)}" th:text="|${#numbers.formatInteger(num, 2)}시|">시간</option>
+								</th:block>
+							</select>
+							<select name="availEdMM" data-valid-name="유효기간종료(분)">
+								<th:block th:each="num: ${#numbers.sequence(0, 59)}">
+									<option th:value="${#numbers.formatInteger(num, 2)}" th:text="|${#numbers.formatInteger(num, 2)}분|">분</option>
+								</th:block>
+							</select>
+						</td>
+					</tr>
+					<tr id="availDaysTr" style="display:none;">
+						<th>유효기간(일)</th>
+						<td><input type="text" name="availDays" data-valid-type="integer"></td>
+					</tr>
+					<tr>
+						<th>발급사유</th>
+						<td>
+							<select name="pubReason" data-valid-name="발급사유" required>
+								<option th:if="${cpnPubReasonList}" th:each="oneData, status : ${cpnPubReasonList}" th:value="${oneData.cd}"
+										th:text="${'[' + oneData.cd + '] ' + oneData.cdNm}"></option>
+							</select>
+						</td>
+						<th>만료알림발송여부<em class="required" title="필수"></em></th>
+						<td>
+							<select name="endAlimSendYn" id="endAlimSendYn" data-valid-name="만료알림발송여부" required="required">
+								<option value="Y">Y</option>
+								<option value="N" selected="selected">N</option>
+							</select>
+						</td>
+					</tr>
+					<tr>
+						<th>상세사유</th>
+						<td colspan="3">
+							<textarea name="pubReasonDtl" class="textareaR3" style="resize: none;"  data-valid-name="상세사유" required="required"></textarea>
+						</td>
+					</tr>
+				</table>
+			</form>
+			<!-- 버튼 배치 영역 -->
+			<ul class="panelBar">
+				<li class="right">
+					<button type="button" class="btn btn-info btn-lg" id="btnIssueCoupon">발급</button>
+				</li>
+			</ul>
+			<!-- //버튼 배치 영역 -->
+		</div>
+	</div>
+</div>
+
+<script th:inline="javascript">
+/*<![CDATA[*/
+	const START_END_TIME = '00';
+	const END_TIME = '59';
+
+	let elementCustNo = [[${elementCustNo}]];
+
+	let siteList = gagajf.convertToArray([[${siteList}]]);
+	let usableCustGbList = gagajf.convertToArray([[${usableCustGbList}]]);
+	let cpnTypeList = gagajf.convertToArray([[${cpnTypeList}]]);
+	let dcWayList = gagajf.convertToArray([[${dcWayList}]]);
+	
+	let columnDefsCouponList = [
+// 		{width: 40, minWidth: 40, cellClass: 'text-center', headerCheckboxSelection: true, checkboxSelection: true, filter: false},
+		{
+			headerName: "사이트", field: "siteCd", width: 80, cellClass: "text-center", pinned: 'left',
+			valueFormatter: function (params) { return gagaAgGrid.lookupValue(siteList, params.value); }
+		},
+		{headerName: "쿠폰ID", field: "cpnId", width: 90, cellClass: 'text-center', pinned: 'left'},
+		{headerName: "쿠폰명", field: "cpnNm", width: 150, pinned: 'left'},
+		{
+			headerName: "사용가능고객", field: "usableCustGb", width: 120, cellClass: "text-center",
+			valueFormatter: function (params) { return gagaAgGrid.lookupValue(usableCustGbList, params.value); }
+		},
+		{
+			headerName: "쿠폰유형", field: "cpnType", width: 100, cellClass: "text-center",
+			valueFormatter: function (params) { return gagaAgGrid.lookupValue(cpnTypeList, params.value); }
+		},
+		{
+			headerName: "할인방식", field: "dcWay", width: 100, cellClass: "text-center",
+			valueFormatter: function (params) { return gagaAgGrid.lookupValue(dcWayList, params.value); }
+		},
+		{
+			headerName: "할인값(PC)", field: "dcPval", width: 100, cellClass: "text-center",
+			cellRenderer: function(params) { return (!gagajf.isNull(params.value) ? gagaAgGrid.toAddComma(params.value) : '') + (params.data.dcWay == '10' ? '원' : '%'); }
+		},
+		{
+			headerName: "할인값(모바일)", field: "dcMval", width: 100, cellClass: "text-center",
+			cellRenderer: function(params) { return (!gagajf.isNull(params.value) ? gagaAgGrid.toAddComma(params.value) : '') + (params.data.dcWay == '10' ? '원' : '%'); }
+		},
+		{
+			headerName: "최고할인값", field: "maxDcAmt", width: 100, cellClass: "text-center",
+			cellRenderer: function(params) { return (!gagajf.isNull(params.value) ? gagaAgGrid.toAddComma(params.value) : '') + (params.data.dcWay == '10' ? '원' : '%'); }
+		},
+		{
+			headerName: "유효기간", field: "availPeriod", width: 300, cellClass: "text-center",
+			cellRenderer: function(params) {
+				return params.data.pdGb == 'P' ? gagaAgGrid.toDateTimeFormat(params.data.availStdt)
+					+ '~' + gagaAgGrid.toDateTimeFormat(params.data.availStdt) : gagaAgGrid.toAddComma(params.data.availDays) + '일';
+			}
+		},
+		{headerName: "발행제한여부", field: "pubLimitYn", width: 100, cellClass: "text-center"},
+		{
+			headerName: "고객당발행제한수량", field: "custPubLimitQty", width: 100, cellClass: "text-center",
+			cellRenderer: function(params) { return !gagajf.isNull(params.value) ? gagaAgGrid.toAddComma(params.value) : ''; }
+		},
+		{
+			headerName: "총발행제한수량", field: "totPubLimitQty", width: 100, cellClass: "text-center",
+			cellRenderer: function(params) { return !gagajf.isNull(params.value) ? gagaAgGrid.toAddComma(params.value) : ''; }
+		},
+		{
+			headerName: "1회발행수량", field: "onePubQty", width: 100, cellClass: "text-center",
+			cellRenderer: function(params) { return !gagajf.isNull(params.value) ? gagaAgGrid.toAddComma(params.value) : ''; }
+		},
+		{headerName: "다운로드구분", field: "dnGb", width: 100, cellClass: "text-center"},
+		{
+			headerName: "구매제한금액", field: "buyLimitAmt", width: 100, cellClass: "text-right",
+			cellRenderer: function(params) { return !gagajf.isNull(params.value) ? gagaAgGrid.toAddComma(params.value) : ''; }
+		}
+	];
+
+	let gridOptionsCouponList = gagaAgGrid.getGridOptions(columnDefsCouponList);
+	
+	gridOptionsCouponList.rowSelection = 'single';
+	gridOptionsCouponList.rowMultiSelectWithClick = true; // 클릭으로 선택 가능
+	//gridOptionsCouponList.suppressRowClickSelection = true;
+
+	// 셀 클릭 이벤트
+	gridOptionsCouponList.onCellClicked = function (event) {
+		fnBindCouponInfo(event.data);
+	};
+
+	// 조회
+	$('#btnSearchCouponRetrieve').on('click', function() {
+		// Fetch data
+		gagaAgGrid.fetch($('#searchCouponForm').prop('action'), gridOptionsCouponList, '#searchCouponForm');
+	});
+	
+
+	// 발생
+	$('#btnIssueCoupon').on('click', function() {
+		let selectedData = gagaAgGrid.selectedRowData(gridOptionsCouponList);
+		if (selectedData.length == 0) {
+			mcxDialog.alert('선택된 쿠폰이 없습니다.');
+			return false;
+		}
+
+		if (!gagajf.validation('#couponIssueForm'))
+			return ;
+
+		let availStHH = $("#couponIssueForm select[name=availStHH]").val();
+		let availStMM = $("#couponIssueForm select[name=availStMM]").val();
+		let availEdHH = $("#couponIssueForm select[name=availEdHH]").val();
+		let availEdMM = $("#couponIssueForm select[name=availEdMM]").val();
+
+		let custCoupon = $("#couponIssueForm").serializeObject();
+		if (custCoupon.pdGb === 'P') {
+			if (gagajf.isNull(custCoupon.availStdt) && gagajf.isNull(custCoupon.availEddt)) {
+				mcxDialog.alert("유효 시작일시 / 유효 종료일시를 입력해주세요");
+				return;
+			}
+			custCoupon.availStdt = custCoupon.availStdt+' '+availStHH +':'+ availStMM + ':' +START_END_TIME;
+			custCoupon.availEddt = custCoupon.availEddt+' '+availEdHH +':'+ availEdMM + ':' +END_TIME;
+		}
+
+		if (custCoupon.pdGb === 'D') {
+			if (gagajf.isNull(custCoupon.availDays)) {
+				mcxDialog.alert("유효기간(일)을 입력해주세요");
+				return;
+			}
+		}
+
+		mcxDialog.confirm("저장하시겠습니까?", {
+			cancelBtnText: "취소",
+			sureBtnText: "확인",
+			sureBtnClick: function () {
+				let jsonData = JSON.stringify(custCoupon);
+				//console.log(jsonData);
+				gagajf.ajaxJsonSubmit('/marketing/coupon/issue/save', jsonData, fnIssueCouponCallBack);
+			}
+		});
+
+	});
+
+	var fnIssueCouponCallBack = function () {
+		uifnPopupClose('popupCouponIssue');
+		fnSearchCoupon();
+	}
+
+
+
+	// 선택 쿠폰정보 셋팅
+	var fnBindCouponInfo = function(params) {
+		$('#couponIssueForm input[name=cpnId]').val(params.cpnId);
+		$('#couponIssueForm input[name=pdGb]').val(params.pdGb);
+		$('#couponIssueForm input[name=availStdt]').val(gagaAgGrid.toDateFormat(params.availStdt));
+		$("#couponIssueForm select[name=availStHH]").val(params.availStdt.substring(8,10));
+		$("#couponIssueForm select[name=availStMM]").val(params.availStdt.substring(10,12));
+		$('#couponIssueForm input[name=availEddt]').val(gagaAgGrid.toDateFormat(params.availEddt));
+		$("#couponIssueForm select[name=availEdHH]").val(params.availEddt.substring(8,10));
+		$("#couponIssueForm select[name=availEdMM]").val(params.availEddt.substring(10,12));
+		$('#couponIssueForm input[name=availDays]').val(params.availDays);
+
+		//유효기간 숨김처리
+		if (params.pdGb === 'P') {
+			$("#availTermsTr").show();
+			$("#availDaysTr").hide();
+		} else if (params.pdGb === 'D') {
+			$("#availTermsTr").hide();
+			$("#availDaysTr").show();
+		}
+
+	}
+
+	var fnInitDataSet = function () {
+		let custNo = $(elementCustNo).val();
+		if(!gagajf.isNull(custNo)) {
+			$('#couponIssueForm input[name=custNo]').val(custNo);
+		}
+	};
+
+	$(document).ready(function() {
+		// Create a agGrid
+		gagaAgGrid.createGrid('gridCouponList', gridOptionsCouponList);
+
+		fnInitDataSet();
+
+
+	});
+/*]]>*/
+</script>
+
+</html>

+ 12 - 10
src/main/webapp/WEB-INF/views/marketing/MorebetterPopupForm.html

@@ -698,20 +698,22 @@
 
 		var jsonData = JSON.stringify(data);
 
-		//gagajf.ajaxJsonSubmit($('#moreBetterForm').prop('action'), jsonData, fnMorebetterSaveCollback);
+		gagajf.ajaxJsonSubmit($('#moreBetterForm').prop('action'), jsonData, fnMorebetterSaveCollback);
 	});
 
 	var fnMorebetterSaveCollback = function(result){
-		console.log('duplicateYn::::'+result.duplicateYn);
+		mcxDialog.alert(result.message);
+
 		if(result.duplicateYn == "Y"){
-			console.log('duplicateGoodsList Size::'+ result.duplicateGoodsList.length);
+			//console.log('duplicateGoodsList Size::'+ result.duplicateGoodsList.length);
 			for(let i=0; i<result.duplicateGoodsList.length; i++){
 				gagaAgGrid.addRowData(gridOptionsDuplicateGoodsList, {"goodsCd" : result.duplicateGoodsList[i].goodsCd, "goodsNm" : result.duplicateGoodsList[i].goodsNm});
 			}
 			mcxDialog.alert("다른 다다익선에서 사용중인 상품이 존재합니다.");
 			gagaAgGrid.exportToExcel('다다익선 중복상품 목록', gridOptionsDuplicateGoodsList);
-
-			return;
+			fnMorebetterFormClose();
+			$('#btnInit').trigger('click');
+			$('#btnSearch').trigger('click');
 		}else{
 			//mcxDialog.alert(result.message);
 			fnMorebetterFormClose();
@@ -739,11 +741,11 @@
 		}
 
 		// 브랜드 데이터 체크
-		let allBrandCnt = gagaAgGrid.getAllRowData(gridOptionsFGBrandList).length;
+		/*let allBrandCnt = gagaAgGrid.getAllRowData(gridOptionsFGBrandList).length;
 		if(allBrandCnt<1){
 			mcxDialog.alert('브랜드를 추가해주세요.');
 			return;
-		}
+		}*/
 	};
 
 	// 브랜드 설정 / 브랜드 추가 콜백함수 (단수로 가져오므로 복수일 경우에 수정 확인 필요)
@@ -763,13 +765,13 @@
 		}
 
 		// 공급업체 데이터 체크
-		var allSupplyCompData = gagaAgGrid.getAllRowData(gridOptionsFGCompanyList);
+		/*var allSupplyCompData = gagaAgGrid.getAllRowData(gridOptionsFGCompanyList);
 		var allBrandData = gagaAgGrid.getAllRowData(gridOptionsFGBrandList);
 
 		if(allSupplyCompData.length < 1){
 			mcxDialog.alert('공급업체를 추가해주세요.');
 			return;
-		}
+		}*/
 	};
 
 	// 분담업체율 설정 / 업체 추가 콜백함수
@@ -841,7 +843,7 @@
 
 	// 공급업체 설정 업체 추가 버튼 클릭시
 	$('#moreBetterForm #btnAddCompany').on('click', function() {
-		cfnOpenCompanyListPopup("fnSetPopupComapnyInfo");
+		cfnOpenCompanyListPopup("fnSetPopupComapnyInfo", "M");
 	});
 
 	// 브랜드 추가 버튼 클릭시 (복수 브랜드때 수정 필요)

+ 19 - 8
src/main/webapp/WEB-INF/views/marketing/PointGrantPopupForm.html

@@ -38,31 +38,31 @@
 						<tr >
 							<th>사이트</th>
 							<td>
-								<select name="siteCd" data-valid-name="사이트" required>
-									<option th:if="${siteCdList}" th:each="oneData, status : ${siteCdList}" th:value="${oneData.cd}" th:text="${oneData.cdNm}"></option>
+								<select name="siteCd" data-valid-name="사이트" required="required">
+									<option th:if="${siteCdList}" th:each="oneData, status : ${siteCdList}" th:value="${oneData.cd}" th:text="${'[' + oneData.cd + '] '+ oneData.cdNm}"></option>
 								</select>
 							</td>
 						</tr>
 						<tr>
 							<th>포인트변경사유<em class="required" title="필수"></em></th>
 							<td>
-								<select name="occurGb" data-valid-name="포인트변경사유" required>
+								<select name="occurGb" data-valid-name="포인트변경사유" required="required">
 									<option value="">선택하세요</option>
-									<option th:if="${occurGbList}" th:each="oneData, status : ${occurGbList}" th:value="${oneData.cd}" th:text="${oneData.cdNm}"></option>
+									<option th:if="${occurGbList}" th:each="oneData, status : ${occurGbList}" th:value="${oneData.cd}" th:text="${'[' + oneData.cd + '] '+ oneData.cdNm}"></option>
 								</select>
 							</td>
 						</tr>
 						<tr>
 							<th>증감구분<em class="required" title="필수"></em></th>
 							<td>
-								<select name="signGb" data-valid-name="증감구분" required>
+								<select id="signGb" name="signGb" data-valid-name="증감구분" required="required">
 									<option value="">선택하세요</option>
 									<option value="+">증가</option>
 									<option value="-">감소</option>
 								</select>
 							</td>
 						</tr>
-						<tr class="expire">
+						<tr id="expire">
 							<th >만료일자</th>
 							<td>
 								<input type="text" name="expBeDt" th:value="${expBeDt}" class="schDate w100"/>
@@ -71,13 +71,13 @@
 						<tr>
 							<th>적립포인트</th>
 							<td>
-								<input type="text" name="pntAmt" min="1" data-valid-name="적립포인트" data-valid-type="integer" maxlength="6" required/>
+								<input type="text" name="pntAmt" min="1" data-valid-name="적립포인트" data-valid-type="integer" maxlength="6" required="required"/>
 							</td>
 						</tr>
 						<tr>
 							<th>상세사유</th>
 							<td colspan="3">
-								<textarea name="occurDtlDesc" class="textareaR4" style="resize: none;" data-valid-name="상세사유" required></textarea>
+								<textarea name="occurDtlDesc" class="textareaR4" style="resize: none;" data-valid-name="상세사유" required="required"></textarea>
 							</td>
 						</tr>
 						</tbody>
@@ -95,9 +95,19 @@
 </div>
 <script th:inline="javascript">
 	/*<![CDATA[*/
+	const END_TIME = '23:59:59';
 	const elementCustNo = [[${elementCustNo}]];
 	const pntAssignAmt = [[${pntAssignAmt}]];
 
+	$('#signGb').on('change',function () {
+		let signGb = $(this).val();
+		if (signGb === '+') {
+			$('#expire').show();
+		} else {
+			$('#expire').hide();
+		}
+	});
+
 	// 포인트 부여
 	$('#btnSavePoint').on('click', function () {
 		if(!gagajf.validation('#pointGrantForm'))
@@ -124,6 +134,7 @@
 		// (+ + 1) -> 1, (- + 1) -> -1
 		let pntAmt = grantPoint.pntAmt * (grantPoint.signGb + 1)
 		grantPoint.pntAmt = pntAmt;
+		grantPoint.expBeDt = grantPoint.expBeDt+' '+END_TIME;
 
 		mcxDialog.confirm("포인트를 부여하시겠습니까?", {
 			cancelBtnText: "취소",

+ 2 - 2
src/main/webapp/WEB-INF/views/order/ExchangeRequestForm.html

@@ -281,9 +281,9 @@ var columnExchangeReqList = [
 					strVal += '<select class="ordChgOpt" name="ordChgOpt" ordDtlNo="' + params.data.ordDtlNo + '" ordDtlItemSq="' + params.data.ordDtlItemSq + '" onchange="fnChangeOption(this)">';
 					
 					if (gagajf.isNull(ordChgOpt)) {
-						strVal += '<option value="">선택</option>'
+						strVal += '<option value="">선택</option>';
 					} else {
-						strVal += '<option value="" selected>선택</option>'
+						strVal += '<option value="" selected>선택</option>';
 					}
 
 					$.each(optArr, function(idx,item){

+ 6 - 0
src/main/webapp/WEB-INF/views/order/OrderListForm.html

@@ -216,6 +216,7 @@
 			<ul class="panelBar">
 				<li>
 					<button type="button" class="btn btn-info btn-lg" onclick="fnOrderExcelList();">엑셀다운로드</button>
+					<button type="button" class="btn btn-info btn-lg" th:if="${userNo == 8 or userNo == 14 or userNo == 11}" onclick="fnCreateSampleOrder();">주문생성</button>
 				</li>
 				<li class="aR">
 					검색결과 : <strong><span id="rowCntOrderList">0</span> 건</strong>&nbsp;
@@ -743,6 +744,11 @@ $(document).ready(function() {
 	gagaAgGrid.createGrid('gridOrderList', gridOptionsOrderList);
 	gridOptionsOrderList.api.hideOverlay();
 });
+
+var fnCreateSampleOrder = function() {
+	var actionUrl = "/order/sample/create/form";
+	cfnOpenModalPopup(actionUrl, "popupOrderSample");
+}
 </script>
 
 </html>

+ 437 - 0
src/main/webapp/WEB-INF/views/order/OrderSamplePopupForm.html

@@ -0,0 +1,437 @@
+<!DOCTYPE html>
+<html lang="ko"
+	xmlns:th="http://www.thymeleaf.org">
+<!--
+ *******************************************************************************
+ * @source  : OrderSamplePopupForm.html
+ * @desc    : 주문 샘플 데이터 생성 팝업 Page
+ *============================================================================
+ * STYLE24
+ * Copyright(C) 2020 TSIT, All rights reserved.
+ *============================================================================
+ * VER  DATE         AUTHOR      DESCRIPTION
+ * ===  ===========  ==========  =============================================
+ * 1.0  2021.01.30   card007     최초 작성
+ *******************************************************************************
+ -->
+<div class="modalPopup" data-width="1200" id="popupOrderSample">
+	<div class="panelStyle">
+		<!-- TITLE -->
+		<div class="panelTitle">
+			<strong th:text="${'주문 샘플 데이터 생성'}"></strong>
+			<button type="button" class="close" onclick="uifnPopupClose('popupOrderSample');"><em class="fa fa-times"></em></button>
+		</div>
+		<!-- //TITLE -->
+		
+		<!-- CONTENT -->
+		<div class="panelContent">
+			<form id="orderSamplePopupForm" name="orderSamplePopupForm" action="#" th:action="@{'/order/sample/create'}" th:method="post">
+				<table class="frmStyle" aria-describedby="등록폼">
+					<colgroup>
+						<col style="width:7%;"/>
+						<col style="width:26%;"/>
+						<col style="width:7%;"/>
+						<col style="width:26%;"/>
+						<col style="width:7%;"/>
+						<col/>
+					</colgroup>
+					<tbody>
+						<tr>
+							<th>회원번호</th>
+							<td>
+								<input class="w200" type="text" name="custNo" id="custNo"/>
+								<button type="button" class="btn btn-info btn-lg" id="btnOrderSearch" onclick="fnApplyCustomerInfo()">적용</button>
+							</td>
+							<th>주문자명</th>
+							<td>
+								<input type="text" name="ordNm" id="ordNm"/>
+							</td>
+							<th>핸드폰번호</th>
+							<td>
+								<input type="text" name="ordPhnno" id="ordPhnno"/>
+							</td>
+						</tr>
+						<tr>
+							<th>전화번호</th>
+							<td>
+								<input type="text" name="ordTelno" id="ordTelno"/>
+							</td>
+							<th>이메일</th>
+							<td colspan="3">
+								<input type="text" name="ordEmail" id="ordEmail"/>
+							</td>
+						</tr>
+						<tr>
+							<th>배송지</th>
+							<td colspan="5">
+								<input type="text" name ="recipZipcode" id="recipZipcode" class="w100" readonly="readonly"/>
+								<button type="button" class="btn btn-info" onclick="fnOpenDaumAddr('delivery');">우편번호찾기</button>
+								<input type="text" name ="recipBaseAddr" id="recipBaseAddr" class="w300"/>
+								<input type="text" name ="recipDtlAddr" id="recipDtlAddr" class="w300"/>
+							</td>
+						</tr>
+					</tbody>
+				</table>
+			</form>
+		</div>
+		<!-- //CONTENT -->
+
+		<!-- Grid -->
+		<ul class="panelBar">
+			<li class="left">
+				<button type="button" class="btn btn-danger btn-lg" onclick="fnGoodsDeleteRow();">행삭제</button>
+			</li>
+			<li class="right">
+				<button type="button" class="btn btnRight btn-base btn-lg" onclick="fnOpenGoodsPopup();">주문상품추가</button>
+			</li>
+		</ul>
+		<div id="gridGoodsList" style="height: 390px;" class="ag-theme-balham lh60"></div>
+		<!-- //Grid -->
+
+		<!-- 버튼 배치 영역 -->
+		<ul class="panelBar">
+			<li class="right">
+				<button type="button" class="btn btn-info btn-lg" id="btnCreateOrderSample">저장</button>
+			</li>
+		</ul>
+		<!-- //버튼 배치 영역 -->
+	</div>
+</div>
+
+<script th:inline="javascript">
+/*<![CDATA[*/
+	var sessRoleCd = [[${sessionInfo.roleCd}]];
+	var goodsStatList = gagajf.convertToArray([[${goodsStatList}]]);
+	var formalGbList = gagajf.convertToArray([[${formalGbList}]]);
+	var seasonList = gagajf.convertToArray([[${seasonList}]]);
+	var columnDefs = [];
+	columnDefs = [
+		{width: 40, minWidth: 40, cellClass: 'text-right', headerCheckboxSelection: true, checkboxSelection: true, filter: false},
+		{headerName: 'No', width: 60, cellClass: 'text-center',
+			valueGetter: function(params) { return cfnGridNumner('searchForm',params.node.rowIndex, 'A');}
+		},
+		{headerName: "이미지", field: "sysImgNm", width: 100, height: 60, cellClass: 'text-center'
+			,cellRenderer: function(params) {
+				return '<img width="60" src="'+ _goodsUrl+ "/" + params.value + '" alt="" onclick="cfnOpenImagePreViewPopup(\'goodsImgView\', \''+ _goodsUrl+ "/" + params.value +'\')" onerror="this.src=\'/image/no.gif\';"/>';
+			}
+		},
+		{headerName: "상품코드", field: "goodsCd", width: 140, cellClass: 'text-center'},
+		{headerName: "상품명", field: "goodsNm", width: 200, cellClass: 'text-left'
+			,cellRenderer: function(params) {
+				return '<a href="javascript:void(0);">' + params.value + '</a>';
+			}
+		},
+		{headerName: "구성상품코드", field: "compsGoodsCd", width: 140, cellClass: 'text-center'},
+		{headerName: "판매가능재고", field: "stockQtySum", width: 120, cellClass: 'text-right',
+			valueFormatter: function(params) {	return params.value.addComma();},
+			cellStyle : function(params){
+				if ("00" == params.data.goodsStat  || "10" == params.data.goodsStat || "20" == params.data.goodsStat || "30" == params.data.goodsStat) {
+					return;
+				}
+				var color = "";
+				if (params.value <= 0){
+					color = '#ff96689c';
+				}
+				return { 'background-color': color};
+			}
+		},
+		{
+			headerName		: "주문옵션"
+			, field			: "optCd"
+			, width			: 100
+			, cellClass		: "text-center"
+			, cellRenderer	: function (params) {
+				var strVal			= '';
+				if (!gagajf.isNull(params.data.optCd2)) {
+					var optArr = params.data.optCd2.split(',');
+					strVal += '<select class="optCd2" name="optCd2" goodsCd="' + params.data.goodsCd + '" onchange="fnChangeOption(this)">';
+					if (gagajf.isNull(params.data.optCd)) {
+						strVal += '<option value="" selected>선택</option>';	
+					} else {
+						strVal += '<option value="">선택</option>'
+					}
+					
+					
+					$.each(optArr, function (idx, item) {
+						if (params.data.optCd == item) {
+							strVal += '<option value="' + item + '" selected>' + item + '</option>';
+						} else {
+							strVal += '<option value="' + item + '">' + item + '</option>';
+						}
+					});
+				}
+				
+				return strVal;
+			}
+		},
+		{headerName: "주문수량", field: "ordQty", width: 100, cellClass: 'text-center', editable : true},
+		{headerName: "상품상태", field: "goodsStat" , width: 100, cellClass: 'text-center',
+			cellEditorParams: { values: gagaAgGrid.extractValues(goodsStatList) },
+			valueFormatter: function (params) { return gagaAgGrid.lookupValue(goodsStatList, params.value); },
+			valueParser: function (params) { return gagaAgGrid.lookupKey(goodsStatList, params.newValue); }
+		},
+		{headerName: "년도", field: "styleYear" , width: 80, cellClass: 'text-center'},
+		{headerName: "시즌", field: "seasonCd" , width: 80, cellClass: 'text-center',
+			cellEditorParams: { values: gagaAgGrid.extractValues(seasonList) },
+			valueFormatter: function (params) { return gagaAgGrid.lookupValue(seasonList, params.value); },
+			valueParser: function (params) { return gagaAgGrid.lookupKey(seasonList, params.newValue); }
+		},
+		{headerName: "정상가", field: "listPrice" , width: 100, cellClass: 'text-right'
+			,valueFormatter: function(params) {return params.value.addComma();},
+			cellEditor: 'textCellEditor',
+			cellEditorParams: { maxlength: 14, validType: 'numeric'}
+		},
+		{headerName: "판매가", field: "currPrice" , width: 100, cellClass: 'text-right'
+			,valueFormatter: function(params) {return params.value.addComma();},
+			cellEditor: 'textCellEditor',
+			cellEditorParams: { maxlength: 14, validType: 'numeric'}
+		},
+		/*{headerName: "할인율", field: "dcRate" , width: 90, cellClass: 'text-right'},*/
+		{headerName: "가격변경일", field: "priceUpdDt", width: 150, cellClass: 'text-center',
+			cellRenderer: function(params) {
+				return !gagajf.isNull(params.value) ? params.value.toDate("YYYYMMDDHHmmss").format("YYYY-MM-DD HH:mm:ss") : '';
+			}
+		},
+		{headerName: "ERP재고연동여부", field: "erpStockLinkYn", width: 120, cellClass: 'text-center'},
+		{headerName: "이월구분", field: "formalGb", width: 100, cellClass: 'text-center',
+			cellEditorParams: { values: gagaAgGrid.extractValues(formalGbList) },
+			valueFormatter: function (params) { return gagaAgGrid.lookupValue(formalGbList, params.value); },
+			valueParser: function (params) { return gagaAgGrid.lookupKey(formalGbList, params.newValue); }
+		},
+		{headerName: "반품가능", field: "returnableYn" , width: 90, cellClass: 'text-center'},
+		{headerName: "등록일시", field: "regDt", width: 150, cellClass: 'text-center',
+			cellRenderer: function(params) {
+				return !gagajf.isNull(params.value) ? params.value.toDate("YYYYMMDDHHmmss").format("YYYY-MM-DD HH:mm:ss") : '';
+			}
+		},
+		{headerName: "등록자", field: "regNm" , width: 100, cellClass: 'text-center'},
+		{headerName: "수정일시", field: "updDt", width: 150, cellClass: 'text-center',
+			cellRenderer: function(params) {
+				return !gagajf.isNull(params.value) ? params.value.toDate("YYYYMMDDHHmmss").format("YYYY-MM-DD HH:mm:ss") : '';
+			}
+		},
+		{headerName: "수정자", field: "updNm" , width: 100, cellClass: 'text-center'}
+	];
+	
+	// Get GridOptions
+	var gridOptions = gagaAgGrid.getGridOptions(columnDefs);
+	
+	// 중복 선택 가능
+	gridOptions.rowSelection = 'multiple';
+	gridOptions.suppressRowClickSelection = true;
+	gridOptions.rowHeight = 60; //이미지가 있을경우 높이 지정해야함.
+	
+	gridOptions.getRowStyle = function(params) {
+		if ("G008_00" == params.data.goodsStat  || "G008_10" == params.data.goodsStat || "G008_20" == params.data.goodsStat || "G008_30" == params.data.goodsStat) {
+			return { background: '#23c6c8' };
+		}
+	}
+
+	// 주문수량 변경 이벤트
+	gridOptions.onCellValueChanged = function(event) {
+		let ordQty = event.data.ordQty;
+		if (event.colDef.field == "ordQty" && event.data.ordQty > event.data.stockQtySum) {
+			ordQty = event.data.stockQtySum;
+			mcxDialog.alert('주문수량이 판매가능재고보다 클 수 없습니다.');
+		}
+		
+		gridOptions.api.forEachNode(function(rowNode, index) {
+			if (event.data.goodsCd == rowNode.data.goodsCd){
+				rowNode.data.ordQty = ordQty;
+				
+				gridOptions.api.updateRowData({update: [rowNode.data]});
+			}
+		});
+	}
+
+	//상품조회 팝업
+	var fnOpenGoodsPopup = function() {
+		cfnOpenGoodsPopup('fnFetchGoods');
+	}
+	
+	// 상품추가
+	var fnFetchGoods = function(goodsData) {
+		if (goodsData.length < 1) return;
+		
+		// 기존상품
+		var oldGoodsSetList = gagaAgGrid.getAllRowData(gridOptions);
+		var index = oldGoodsSetList.length+1;
+		
+		var arrGoodsCd = [];
+		$.each(goodsData, function(idx, item) {
+			arrGoodsCd.push(item.goodsCd);
+		})
+		
+		var isExist = false;
+		var jsonData = JSON.stringify(arrGoodsCd);
+		gagajf.ajaxJsonSubmit('/order/sample/goods/info', jsonData, function(result) {
+			$.each(result, function(idx, item) {
+				isExist = false;
+				gridOptions.api.forEachNode(function(rowNode, index) {
+					//중복상품 여부 확인
+					if (item.goodsCd == rowNode.data.goodsCd){
+						isExist = true;
+					}
+				});
+				
+				if(!isExist){
+					var data = {
+						no: index
+						, sysImgNm : item.sysImgNm
+						, goodsCd : item.goodsCd
+						, compsGoodsCd : item.repGoodsCd
+						, goodsNm : item.goodsNm
+						, ordQty : 1
+						, optCd2 : item.siteCd
+						, stockQtySum : item.stockQtySum
+						, goodsStat : item.goodsStat
+						, styleYear : item.styleYear
+						, seasonCd : item.seasonCd
+						, listPrice : item.listPrice
+						, currPrice : item.currPrice
+						, priceUpdDt : item.priceUpdDt
+						, erpStockLinkYn : item.erpStockLinkYn
+						, formalGb : item.formalGb
+						, returnableYn : item.returnableYn
+						, regDt : item.regDt
+						, regNm : item.regNm
+						, updDt : item.updDt
+						, updNm : item.updNm
+					};
+					
+					//그리드 마지막에 추가해야함
+					gridOptions.api.updateRowData({add: [data], addIndex: idx});
+					gridOptions.api.refreshCells();
+					index++;
+				}
+			});
+		});
+	}
+
+	//상품삭제
+	var fnGoodsDeleteRow = function() {
+		var selectedData = gagaAgGrid.selectedRowData(gridOptions);
+		
+		if (selectedData.length == 0) {
+			mcxDialog.alert('선택된 행이 없습니다.');
+			return;
+		}
+		
+		//화면에서 삭제
+		gagaAgGrid.removeRowData(gridOptions, false);
+	}
+
+	// 저장
+	$('#btnCreateOrderSample').on('click', function() {
+		// 입력 값 체크
+		let selectedData = gagaAgGrid.selectedRowData(gridOptions);
+		
+		if (selectedData.length == 0) {
+			mcxDialog.alert('선택된 행이 없습니다.');
+			return;
+		}
+		
+		let optChk = true;
+		let qtyChk = true;
+		$.each(selectedData, function(idx, item) {
+			if (gagajf.isNull(item.optCd)) {
+				optChk = false;
+			} else if (item.ordQty <= 0) {
+				qtyChk = false;
+			}
+		});
+		
+		if (!optChk) {
+			mcxDialog.alert('주문옵션이 없습니다.');
+			return false;
+		}
+		
+		if (!qtyChk) {
+			mcxDialog.alert('주문수량은 0보다 커야 됩니다.');
+			return false;
+		}
+		
+		mcxDialog.confirm("저장하시겠습니까?", {
+			cancelBtnText: "취소",
+			sureBtnText: "확인",
+			sureBtnClick: function() {
+				let params = {};
+				params.custNo = $('#custNo').val();
+				params.ordNm = $('#ordNm').val();
+				params.ordPhnno = $('#ordPhnno').val();
+				params.ordEmail = $('#ordEmail').val();
+				params.recipZipcode = $('#recipZipcode').val();
+				params.recipBaseAddr = $('#recipBaseAddr').val();
+				params.recipDtlAddr = $('#recipDtlAddr').val();
+				params.goods = selectedData;
+				
+				let jsonData = JSON.stringify(params);
+				
+				gagajf.ajaxJsonSubmit($('#orderSamplePopupForm').prop('action'), jsonData, function(result) {
+					uifnPopupClose('popupOrderSample');
+				});
+			}
+		});
+	});
+
+	// 회원정보 적용
+	var fnApplyCustomerInfo = function() {
+		var params = {};
+		params.searchGb = 'custNo';
+		params.searchTxt = $('#orderSamplePopupForm input[name=custNo]').val();
+		
+		var jsonData = JSON.stringify(params);
+		
+		gagajf.ajaxJsonSubmit('/customer/active/list', jsonData, function(result) {
+			let param = result[0];
+			
+			$('#ordNm').val(param.custNm);
+			$('#ordPhnno').val(param.cellPhnno);
+			$('#ordEmail').val(param.email);
+			$('#recipZipcode').val(param.homeZipcode);
+			$('#recipBaseAddr').val(param.homeBaseAddr);
+			$('#recipDtlAddr').val(param.homeDtlAddr);
+		});
+	}
+
+	var fnOpenDaumAddr = function() {
+		let daumZip = new daum.Postcode({
+			oncomplete: function(data) {
+				// 우편번호와 주소 정보를 해당 필드에 넣는다.
+				$('#orderSamplePopupForm input[name=recipZipcode]').val(data.zonecode);
+				$('#orderSamplePopupForm input[name=recipBaseAddr]').val(cfnGetDaumRoadAddr(data));
+				$('#orderSamplePopupForm input[name=recipDtlAddr]').focus();
+				
+				cfnCloseDaumAddr();
+			},
+			width: '100%'
+		});
+		
+		cfnOpenDaumAddr(daumZip);
+	}
+	
+	var fnChangeOption = function(param) {
+		var params = {};
+		params.goodsCd = $(param).attr('goodsCd');
+		params.siteCd = $(param).val();
+		
+		var jsonData = JSON.stringify(params);
+		gagajf.ajaxJsonSubmit('/order/sample/goods/stock', jsonData, function(result) {
+			gridOptions.api.forEachNode(function(rowNode, index) {
+				if (result.goodsCd == rowNode.data.compsGoodsCd){
+					rowNode.data.stockQtySum = result.minOrdQty;
+					console.log(result);
+					rowNode.data.optCd = result.siteCd;
+					gridOptions.api.updateRowData({update: [rowNode.data]});
+				}
+			});
+		});
+	}
+
+	$(document).ready(function() {
+		gagaAgGrid.createGrid('gridGoodsList', gridOptions);
+	});
+/*]]>*/
+</script>
+
+</html>

+ 1 - 1
src/main/webapp/ux/css/admin.ui.css

@@ -599,7 +599,7 @@ hr {border:0; padding-bottom:10px;}/* 기본 여백 :10px */
 .w20 {width:20px !important;}
 .w50 {width:50px !important;}
 .w60 {width:60px !important;}
-.w70 {width:60px !important;}
+.w70 {width:70px !important;}
 .w80 {width:80px !important;}
 .w90 {width:80px !important;}
 .w100 {width:100px !important;}

+ 1 - 1
src/main/webapp/ux/plugins/gaga/gaga.paging.js

@@ -185,7 +185,7 @@ var gagaPaging = {
 				pageTag += "<a class=\"arrow\" href=\"#pageNo="+ (getPageGroup()-1) * pageUnit + "\"><i class=\"fa fa-angle-left\" alt=\"이전페이지\"></i></a>\n"
 			}
 
-			for (let i = firstCount; i < loopCount; i++) {
+			for (var i = firstCount; i < loopCount; i++) {
 				if (pageNo == i) {
 					pageTag += "<a class=\"num on\" href=\"#\">"+ i + "</a>\n";
 				} else {