Просмотр исходного кода

Merge branch 'develop' into eskim

eskim 5 лет назад
Родитель
Сommit
35d09dff5b
26 измененных файлов с 1006 добавлено и 334 удалено
  1. 9 1
      src/main/java/com/style24/admin/biz/dao/TsaCouponDao.java
  2. 1 2
      src/main/java/com/style24/admin/biz/dao/TsaCustomerDao.java
  3. 18 0
      src/main/java/com/style24/admin/biz/dao/TsaFreegiftPromotionDao.java
  4. 44 19
      src/main/java/com/style24/admin/biz/service/TsaCouponService.java
  5. 26 4
      src/main/java/com/style24/admin/biz/service/TsaFreegiftPromotionService.java
  6. 1 0
      src/main/java/com/style24/admin/biz/service/TsaSystemService.java
  7. 102 12
      src/main/java/com/style24/admin/biz/web/TsaMarketingController.java
  8. 9 2
      src/main/java/com/style24/admin/biz/web/TsaOrderChangeController.java
  9. 32 1
      src/main/java/com/style24/admin/support/env/TsaConstants.java
  10. 26 0
      src/main/java/com/style24/persistence/domain/CategoryGoods.java
  11. 48 48
      src/main/java/com/style24/persistence/domain/Coupon.java
  12. 2 0
      src/main/java/com/style24/persistence/domain/Order.java
  13. 10 25
      src/main/java/com/style24/persistence/mybatis/shop/TsaCoupon.xml
  14. 32 15
      src/main/java/com/style24/persistence/mybatis/shop/TsaCustomer.xml
  15. 88 1
      src/main/java/com/style24/persistence/mybatis/shop/TsaDsiplay.xml
  16. 77 24
      src/main/java/com/style24/persistence/mybatis/shop/TsaFreegiftPromotion.xml
  17. 18 3
      src/main/webapp/WEB-INF/views/customer/CustomerDetailForm.html
  18. 3 3
      src/main/webapp/WEB-INF/views/customer/LmsPopupForm.html
  19. 94 102
      src/main/webapp/WEB-INF/views/display/CategoryGoodsForm.html
  20. 1 1
      src/main/webapp/WEB-INF/views/marketing/CouponListForm.html
  21. 53 6
      src/main/webapp/WEB-INF/views/marketing/CouponPopupForm.html
  22. 25 9
      src/main/webapp/WEB-INF/views/marketing/FreeGoodsPromotionForm.html
  23. 116 30
      src/main/webapp/WEB-INF/views/marketing/FreeGoodsPromotionRegiForm.html
  24. 156 0
      src/main/webapp/WEB-INF/views/marketing/PointGrantPopupForm.html
  25. 13 12
      src/main/webapp/WEB-INF/views/order/ExchangeRequestForm.html
  26. 2 14
      src/main/webapp/ux/js/admin.popup.js

+ 9 - 1
src/main/java/com/style24/admin/biz/dao/TsaCouponDao.java

@@ -194,13 +194,21 @@ public interface TsaCouponDao {
 	void createRandomCouponInfo(Coupon param);
 
 	/**
-	 * 동일 쿠폰명이 존재하는지 확인
+	 * 동일 쿠폰명이 같은 기간에 존재하는지 확인
 	 * @param param
 	 * @author xodud1202
 	 * @since 2021. 01. 26
 	 */
 	int getSerialOverlapCheck(Coupon param);
 
+	/**
+	 * 동일 쿠폰명이 존재하는지 확인
+	 * @param param
+	 * @author xodud1202
+	 * @since 2021. 01. 27
+	 */
+	int getRandomCouponNmCnt(String param);
+
 	/**
 	 * 동일 쿠폰명이 존재하는지 확인
 	 * @param param

+ 1 - 2
src/main/java/com/style24/admin/biz/dao/TsaCustomerDao.java

@@ -16,7 +16,7 @@ import com.style24.persistence.domain.Review;
 import org.springframework.stereotype.Repository;
 
 import java.util.Collection;
-import java.util.concurrent.CompletionException;
+
 
 /**
  * 회원 Dao
@@ -45,7 +45,6 @@ public interface TsaCustomerDao {
 	 */
 	void updateCustomerInfo(Customer customer);
 
-
 	/**
 	 * 회원 휴대전화번호 수정
 	 * @param customer - 고객정보

+ 18 - 0
src/main/java/com/style24/admin/biz/dao/TsaFreegiftPromotionDao.java

@@ -26,6 +26,24 @@ public interface TsaFreegiftPromotionDao {
 	 */
 	Collection<FreeGoodsPromotion> getFreeGoodsPromotionList(FreeGoodsPromotion param);
 
+	/**
+	 * 사은품 프로모션 리스트 COUNT
+	 * @param param
+	 * @return
+	 * @author xodud1202
+	 * @since 2020. 12. 27
+	 */
+	int getFreeGoodsPromotionListCount(FreeGoodsPromotion param);
+
+	/**
+	 * 사은품 프로모션 디테일
+	 * @param param
+	 * @return
+	 * @author xodud1202
+	 * @since 2021. 01. 28
+	 */
+	FreeGoodsPromotion getFreeGoodsPromotionInfo(FreeGoodsPromotion param);
+
 	/**
 	 * 사은품 프로모션 등록 제휴몰 리스트 조회
 	 * @param param

+ 44 - 19
src/main/java/com/style24/admin/biz/service/TsaCouponService.java

@@ -1,25 +1,19 @@
 package com.style24.admin.biz.service;
 
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-
 import com.google.gson.Gson;
 import com.google.gson.reflect.TypeToken;
+import com.style24.admin.biz.dao.TsaCouponDao;
+import com.style24.admin.support.env.TsaConstants;
+import com.style24.admin.support.security.session.TsaSession;
 import com.style24.persistence.domain.*;
-import org.apache.commons.lang3.StringUtils;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.style24.admin.biz.dao.TsaCouponDao;
-import com.style24.admin.support.security.session.TsaSession;
-
-import lombok.extern.slf4j.Slf4j;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Random;
 
 /**
  * 쿠폰 Service
@@ -45,7 +39,7 @@ public class TsaCouponService {
 	 */
 	@Transactional("shopTxnManager")
 	public String saveCoupon(Coupon params){
-		int cpnId = 0;		// 쿠폰ID
+		int cpnId = params.getCpnId();		// 쿠폰ID (신규생성인지 수정인지 구분하기 위해 params의 cpnId를 먼저 가져옴 > 쿠폰 생성시 cpnId를 저장하기때문임)
 		params.setRegNo(TsaSession.getInfo().getUserNo());
 		params.setUpdNo(TsaSession.getInfo().getUserNo());
 
@@ -153,7 +147,7 @@ public class TsaCouponService {
 		}
 
 		// 수정모드이고 변경된 쿠폰상태가 대기 , 중지 인경우 고객이 발급받은 내용도 변경
-		if(params.getCpnId() != 0 &&
+		if(cpnId != 0 &&
 				(params.getCpnStat().equals("G232_10") || params.getCpnStat().equals("G232_12")) ) {
 
 			CustCoupon custCoupon = new CustCoupon();
@@ -171,10 +165,8 @@ public class TsaCouponService {
 			}
 		}
 
-		log.info("CHECK GUBUN >> " + params.getCpnType() + " / " + params.getDcCdGb() + " / " + params.getTotPubLimitQty());
-
-		// 시리얼 쿠폰 생성
-		if("G230_20".equals(params.getCpnType()) && "G233_10".equals(params.getDcCdGb())) {
+		// 시리얼 쿠폰 생성(최초 쿠폰 생성일 경우에만)
+		if(cpnId == 0 && params.getCpnType().equals(TsaConstants.CpnType.PAY_CPN.value()) && params.getDcCdGb().equals(TsaConstants.DcCdGb.SERIAL.value())) {
 			// 시리얼 쿠폰명이 동일한 쿠폰이 일정 겹치는 부분이 있는지 확인
 			int overlapCheck = couponDao.getSerialOverlapCheck(params);
 			if(overlapCheck < 1) {
@@ -184,6 +176,39 @@ public class TsaCouponService {
 			} else {
 				throw new IllegalStateException("같은 시리얼명이 사용되는 쿠폰이 중복됩니다. 기간을 확인해주세요.");
 			}
+		} else if(cpnId == 0 && params.getCpnType().equals(TsaConstants.CpnType.PAY_CPN.value()) && params.getDcCdGb().equals(TsaConstants.DcCdGb.RANDOM.value())) {
+			Random random = new Random();
+			String prefixRandomCpn = "" + params.getCpnId();		// 랜덤 번호는 쿠폰번호 + 랜덤문자 = 12로 처리함
+			// 랜덤 문자 발급 수 만큼 진행
+			for(int j = 0 ; j < params.getTotPubLimitQty() ; j++) {
+				boolean chk = true;
+				while (chk) {
+					// 대문자+소문자+숫자 조합 10자리 인증번호 생성
+					StringBuilder sb = new StringBuilder();
+					// 쿠폰번호 + 랜덤글자 = 12 글자만큼 생성
+					for (int i = 0; i < 12 - prefixRandomCpn.length(); i++) {
+						int index = random.nextInt(2);
+						switch (index) {
+							case 0:
+								sb.append((char) (random.nextInt(26) + 65));
+								break;
+							case 1:
+								sb.append(random.nextInt(10));
+								break;
+						}
+					}
+
+					// 인증번호 중복 체크
+					int cnt = couponDao.getRandomCouponNmCnt(sb.toString());
+
+					if (cnt == 0) {
+						// 인증번호 설정
+						params.setRdCpnNm(sb.substring(0, 4) + params.getCpnId() + sb.substring(4));
+						couponDao.createRandomCouponInfo(params);
+						chk = false;
+					}
+				}
+			}
 		}
 
 		return "SUCCESS";

+ 26 - 4
src/main/java/com/style24/admin/biz/service/TsaFreegiftPromotionService.java

@@ -38,6 +38,28 @@ public class TsaFreegiftPromotionService {
 		return freegiftPromotionDao.getFreeGoodsPromotionList(param);
 	}
 
+	/**
+	 * 사은품 프로모션 디테일
+	 * @param param
+	 * @return Collection<FreeGoodsPromotion>
+	 * @author xodud1202
+	 * @since 2021. 01. 28
+	 */
+	public FreeGoodsPromotion getFreeGoodsPromotionInfo(FreeGoodsPromotion param) {
+		return freegiftPromotionDao.getFreeGoodsPromotionInfo(param);
+	}
+
+	/**
+	 * 사은품 프로모션 카운트
+	 * @param param
+	 * @return Collection<FreeGoodsPromotion>
+	 * @author xodud1202
+	 * @since 2020. 12. 17
+	 */
+	public int getFreeGoodsPromotionListCount(FreeGoodsPromotion param) {
+		return freegiftPromotionDao.getFreeGoodsPromotionListCount(param);
+	}
+
 	/**
 	 * 사은품 프로모션 디테일 조회
 	 * @param param
@@ -49,12 +71,12 @@ public class TsaFreegiftPromotionService {
 		GagaMap result = new GagaMap();
 
 		// 사은품 프로모션 마스터 정보 조회
-		List<FreeGoodsPromotion> freeGoodsList = (ArrayList<FreeGoodsPromotion>) getFreeGoodsPromotionList(param);
-		// 상세 조회 내역이 없거나, 1개가 아닐 경우
-		if(freeGoodsList == null || freeGoodsList.size() != 1 ) {
+		FreeGoodsPromotion freegift = getFreeGoodsPromotionInfo(param);
+		// 상세 조회 내역이 없경우
+		if(freegift == null || freegift.getFreegiftSq() == 0 ) {
 			return null;
 		}
-		FreeGoodsPromotion freegift = freeGoodsList.get(0);							// 사은품 프로모션 마스터 정보
+
 		freegift.setExtmallList(getFreegiftExtmallList(param));						// 사은품 프로모션 제휴몰 정보
 		freegift.setBrandList(freegiftPromotionDao.getFreegiftBrandList(param));			// 사은품 프로모션 브랜드 정보
 		freegift.setSupplyCompList(freegiftPromotionDao.getFreegiftSupplyCompList(param));	// 사은품 프로모션 공급업체 정보

+ 1 - 0
src/main/java/com/style24/admin/biz/service/TsaSystemService.java

@@ -205,6 +205,7 @@ public class TsaSystemService {
 	 * @param user - 사용자 정보
 	 * @since 2020. 10. 7
 	 */
+	@Transactional("shopTxnManager")
 	public void updateUserPassword(User user) {
 		systemDao.updateUserPassword(user);
 

+ 102 - 12
src/main/java/com/style24/admin/biz/web/TsaMarketingController.java

@@ -3,6 +3,12 @@ package com.style24.admin.biz.web;
 import java.text.SimpleDateFormat;
 import java.util.*;
 
+import com.gagaframework.web.util.GagaDateUtil;
+import com.style24.admin.biz.service.TsaSystemService;
+import com.style24.core.biz.service.TscPointService;
+import com.style24.core.support.env.TscConstants;
+import com.style24.persistence.domain.Point;
+import com.style24.persistence.domain.User;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.env.Environment;
@@ -75,6 +81,12 @@ public class TsaMarketingController extends TsaBaseController {
 	@Autowired
 	private TsaReviewService reviewService;
 
+	@Autowired
+	private TsaSystemService systemService;
+
+	@Autowired
+	private TscPointService corePointService;
+
 	/**
 	 * 상품평관리 화면
 	 * @return
@@ -176,14 +188,12 @@ public class TsaMarketingController extends TsaBaseController {
 	public GagaMap getFreeGoodsPromotionList(@RequestBody FreeGoodsPromotion param) {
 		GagaMap result = new GagaMap();
 
-		List<FreeGoodsPromotion> freeGoodsList = (ArrayList<FreeGoodsPromotion>)freegiftService.getFreeGoodsPromotionList(param);
-
 		param.setRegNo(TsaSession.getInfo().getUserNo()); // 엑셀조회시 로그인 사용자의 엑셀 상품조회시 사용
 		param.setPageable(new TscPageRequest(param.getPageNo() - 1, param.getPageSize()));
-		param.getPageable().setTotalCount(freeGoodsList.size());
+		param.getPageable().setTotalCount(freegiftService.getFreeGoodsPromotionListCount(param));
 
 		result.set("pageing", param);
-		result.set("freeGoodsList", freeGoodsList);
+		result.set("freeGoodsList", freegiftService.getFreeGoodsPromotionList(param));
 
 		return result;
 	}
@@ -200,10 +210,37 @@ public class TsaMarketingController extends TsaBaseController {
 	public ModelAndView freeGoodsRegiForm(FreeGoodsPromotion param) {
 		ModelAndView mav = new ModelAndView();
 
-		// 상품상태
-		String[] exceptCds = {"G008_00"};
-		mav.addObject("goodsStatList", rendererService.getCommonCodeList("G008", "Y", exceptCds));
+		String num = "";
+		CommonCode temp = new CommonCode();
 
+		// 행사기간 시 리스트 세팅
+		Collection<CommonCode> hhList = new ArrayList<CommonCode>();
+		for (int i = 0; i < 24; i++) {
+			num = "";
+			temp = new CommonCode();
+			if (i < 10) {	num = "0" + i;				}
+			else {			num = String.valueOf(i);	}
+
+			temp.setCd(num);	temp.setCdNm(num + "시");
+			hhList.add(temp);
+		}
+
+		// 행사기간 분 리스트 세팅
+		Collection<CommonCode> mmList = new ArrayList<CommonCode>();
+		for (int i = 0; i < 60; i++) {
+			num = "";
+			temp = new CommonCode();
+			if (i < 10) {	num = "0" + i;				}
+			else {			num = String.valueOf(i);	}
+
+			temp.setCd(num);	temp.setCdNm(num + "분");
+			mmList.add(temp);
+		}
+
+		mav.addObject("hhList", hhList);	// 행사기간 시 리스트 세팅
+		mav.addObject("mmList", mmList);	// 행사기간 분 리스트 세팅
+		String[] exceptCds = {"G008_00"};		// 상품상태
+		mav.addObject("goodsStatList", rendererService.getCommonCodeList("G008", "Y", exceptCds));
 		mav.addObject("param", param);
 
 		mav.setViewName("marketing/FreeGoodsPromotionRegiForm");
@@ -213,7 +250,7 @@ public class TsaMarketingController extends TsaBaseController {
 	/**
 	 * 사은품 프로모션 목록 조회
 	 * @author xodud1202
-	 * @since 2020. 12. 16
+	 * @since 2021. 01. 28
 	 */
 	@PostMapping("/freeGoodsPromotion/detail")
 	@ResponseBody
@@ -338,10 +375,6 @@ public class TsaMarketingController extends TsaBaseController {
 				num = String.valueOf(i);
 			}
 
-			// 상품상태
-			String[] exceptCds = {"G008_00"};
-			mav.addObject("goodsStatList", rendererService.getCommonCodeList("G008", "Y", exceptCds));
-
 			temp.setCd(num);
 			temp.setCdNm(num + "시");
 
@@ -366,6 +399,9 @@ public class TsaMarketingController extends TsaBaseController {
 		mav.addObject("mmList", mmList);
 		// 시간 시 리스트 세팅
 		mav.addObject("hhList", hhList);
+		// 상품상태
+		String[] exceptCds = {"G008_00"};
+		mav.addObject("goodsStatList", rendererService.getCommonCodeList("G008", "Y", exceptCds));
 		// 입점업체 조회
 		mav.addObject("ibSupplyCompList", rendererService.getSupplyCompanyList("", "N"));
 		// 할인 쿠폰 코드 조회
@@ -856,4 +892,58 @@ public class TsaMarketingController extends TsaBaseController {
 	public Collection<Coupon> getCouponRetrieveList(@RequestBody Coupon coupon) {
 		return couponService.getCouponRetrieveList(coupon);
 	}
+
+	/**
+	 * 포인트부여 팝업
+	 * @param elementCustNo - 고객일련번호
+	 * @return ModelAndView
+	 * @author jsshin
+	 * @since 2021. 1. 27
+	 */
+	@GetMapping("/point/grant/popup/form")
+	@ResponseBody
+	public ModelAndView pointGrantPopupForm(@RequestParam(value = "elementCustNo") String elementCustNo) {
+		ModelAndView mav = new ModelAndView();
+
+		mav.addObject("elementCustNo", elementCustNo);
+		// 사이트 목록
+		mav.addObject("siteCdList", rendererService.getAvailCommonCodeList("G000"));
+
+		// 포인트발생구분
+		mav.addObject("occurGbList", rendererService.getCommonCodeList("G069","Y"));
+
+		mav.addObject("expBeDt", GagaDateUtil.getToday("yyyy-MM-dd"));
+
+		User user = systemService.getUser(TsaSession.getInfo().getUserNo());
+
+		// 관리자 포인트할당금액
+		mav.addObject("pntAssignAmt", user.getPntAssignAmt());
+
+		mav.setViewName("marketing/PointGrantPopupForm");
+		return mav;
+	}
+
+	/**
+	 * 포인트 부여
+	 * @param point - 포인트 정보
+	 * @return ModelAndView
+	 * @author jsshin
+	 * @since 2021. 1. 27
+	 */
+	@PostMapping("/point/save")
+	@ResponseBody
+	public GagaResponse savePoint(@RequestBody Point point) {
+		Integer userNo = TsaSession.getInfo().getUserNo();
+		point.setRegNo(userNo);
+		point.setUpdNo(userNo);
+		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"));
+	}
+
 }

+ 9 - 2
src/main/java/com/style24/admin/biz/web/TsaOrderChangeController.java

@@ -530,6 +530,7 @@ public class TsaOrderChangeController extends TsaBaseController {
 		GagaMap result = new GagaMap();
 		result.set("status", GagaResponseStatus.FAIL.getCode());
 
+		// 교환요청 데이터 확인
 		if (excReq == null) {
 			result.set("message", message.getMessage("FAIL_1001"));
 			return result;
@@ -540,10 +541,16 @@ public class TsaOrderChangeController extends TsaBaseController {
 		excReq.setUpdNo(userNo);
 		excReq.setRegNo(userNo);
 
-		log.info("excReq >>> {}", excReq);
-
+		// 교환처리
 		result = coreOrderChangeService.exchReq(excReq);
 
+		// 처리 결과 코드에 따른 메세지 설정
+		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;
 	}
 }

+ 32 - 1
src/main/java/com/style24/admin/support/env/TsaConstants.java

@@ -40,5 +40,36 @@ public class TsaConstants {
 		public String value() {
 			return value;
 		}
-	}	
+	}
+
+	// 쿠폰유형
+	public enum CpnType {
+		CATE_CPN("G230_13"),			// 장바구니쿠폰
+		PAY_CPN("G230_20");			// 주문서쿠폰
+
+		private String value;
+
+		private CpnType(String value) {
+			this.value = value;
+		}
+
+		public String value() {
+			return value;
+		}
+	}
+
+	// 할인 코드 유형
+	public enum DcCdGb {
+		NARMAL("G233_00"),			// 일반 쿠폰 유형
+		SERIAL("G233_10"),			// 시리얼 쿠폰 유형
+		RANDOM("G233_20");			// 랜덤 쿠폰 유형
+
+		private String value;
+
+		private DcCdGb(String value) {	this.value = value;	}
+
+		public String value() {
+			return value;
+		}
+	}
 }

+ 26 - 0
src/main/java/com/style24/persistence/domain/CategoryGoods.java

@@ -15,6 +15,32 @@ import lombok.Data;
 public class CategoryGoods extends TscBaseDomain {
 
 	private Integer cateNo;		// 카테고리번호
+	private Integer selLvl;
+	private String siteCd;
+	private String cateGb;
+	private String cate1No;
+	private String cate2No;
+	private String cate3No;
+	private String cate4No;
+	private String searchGb;
+
+	private int rnum;
+	private String goodsCd;
+	private String goodsTnm;
+	private String goodsNm;
+	private int dispOrd;
+	private String goodsType;
+	private Integer tagPrice;				// tag가
+	private Integer listPrice;				// 정상가
+	private Integer currPrice;				// 현재가
+	private String dcRate;					// 할인율
+	private String goodsStat;
+	private String brandCd;
+	private String supplyGoodsCd;
+	private String styleYear;	//스타일연도
+	private String formalGb;
+
+	private int stockQty;
 
 	// Pagination
 	private TscPageRequest pageable;

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

@@ -17,58 +17,58 @@ import java.util.Collection;
 @Data
 public class Coupon extends TscBaseDomain {
     // TB_COUPON
-    private int     cpnId;					// 쿠폰ID
-    private String  cpnNm;					// 쿠폰명
-    private String  siteCd;					// 사이트코드(공통코드G000)
-    private String  afLinkCd;				// 제휴링크코드
-    private String  usableCustGb;			// 사용가능고객구분(공통코드G100)
-    private String  usableCustGrade;		// 사용가능고객등급(공통코드G110)
-    private String  cpnType;				// 쿠폰유형(공통코드G230)
-    private String  applyScope;				// 적용범위(A:전체, I:개별). "I:개별"이고 쿠폰유형이 "20:장바구니쿠폰" 외 이면 TB_COUPON_REFVAL 참조
-    private String  dcWay;					// 할인방식(공통코드G240)
-    private Integer dcPval;					// 할인값(PC). 할인방식이 금액이면 할인금액, 율이면 할인율
-    private Integer dcMval;					// 할인값(모바일). 할인방식이 금액이면 할인금액, 율이면 할인율
-    private Integer dcAval;					// 할인값(모바일앱)
-    private Integer maxDcAmt;				// 최고할인금액
-    private String  pdGb;					// 기간/일수구분(P:기간, D:일수)
-    private String  availStdt;				// 유효시작일시(기간/일수구분 "P:기간"일 때 사용됨)
-    private String  availEddt;				// 유효종료일시(기간/일수구분 "P:기간"일 때 사용됨)
-    private Integer availDays;				// 유효일수(기간/일수구분 "D:일수"일 때 사용됨)
-    private Integer custPubLimitQty;		// 고객당발행제한수량(0은 무제한)
-    private Integer totPubLimitQty;			// 총발행제한수량(0은 무제한)
-    private Integer onePubQty;				// 1회발행수량(기본은 1)
-    private String  dnGb;					// 다운로드구분(공통코드G058)
-    private String  downStdt;				// 다운로드시작일시
-    private String  downEddt;				// 다운로드종료일시
-    private Integer buyLimitAmt;			// 구매제한금액(0은 제한없음. 그 외는 00 이상 구매 시 사용)
-    private Integer planSq;					// 기획전번호(쿠폰유형이 플러스쿠폰 일 때 사용 기획전번호)
-    private String  reissuance;				// 쿠폰재발급여부(공통코드G231)
-    private String  cpnStat;				// 쿠폰상태(공통코드G232)
-    private String  endAlimYn;				// 만료알림여부
-    private String  firstYn;				// 첫구매여부 (Y:구매이력이없음 | N:구매이력있음)
-    private String  downYn;					// 다운로드가능여부(마이페이지, 상품상세) --> EP쿠폰, 난수쿠폰
-    private String  custJoinStdt;			// 회원가입일자(FROM) 20200101 (신규회원여부의 판단을 가입일자로 설정함)
-    private String  custJoinEddt;			// 회원가입일자(FROM) 20200101 (신규회원여부의 판단을 가입일자로 설정함)
-    private String  buyStdt;				// 회원가입일자(FROM) 20200101 (구매기간일자(FROM) (해당기간에 구매이력이 없으면 다운로드 가능))
-    private String  buyEddt;				// 구매기간일자(TO)
-    private Integer issueCnt;				// 쿠폰발급개수
-    private Integer useCnt;					// 쿠폰사용개수
-    private String  payType;                // 결제수단
-    private String  custJoinYn;             // 신규회원여부
-    private String  afChannel;              // 제휴링크
-    private String  dcCdGb;                 // 할인코드유형 (공통코드G233)
-    private String  rdCpnNm;                // 랜덤쿠폰 사용키 (시리얼명 or 난수)
+    private int    cpnId;					// 쿠폰ID
+    private String cpnNm;					// 쿠폰명
+    private String siteCd;					// 사이트코드(공통코드G000)
+    private String afLinkCd;				// 제휴링크코드
+    private String usableCustGb;			// 사용가능고객구분(공통코드G100)
+    private String usableCustGrade;		    // 사용가능고객등급(공통코드G110)
+    private String cpnType;				    // 쿠폰유형(공통코드G230)
+    private String applyScope;				// 적용범위(A:전체, I:개별). "I:개별"이고 쿠폰유형이 "20:장바구니쿠폰" 외 이면 TB_COUPON_REFVAL 참조
+    private String dcWay;					// 할인방식(공통코드G240)
+    private int    dcPval;					// 할인값(PC). 할인방식이 금액이면 할인금액, 율이면 할인율
+    private int    dcMval;					// 할인값(모바일). 할인방식이 금액이면 할인금액, 율이면 할인율
+    private int    dcAval;					// 할인값(모바일앱)
+    private int    maxDcAmt;				// 최고할인금액
+    private String pdGb;					// 기간/일수구분(P:기간, D:일수)
+    private String availStdt;				// 유효시작일시(기간/일수구분 "P:기간"일 때 사용됨)
+    private String availEddt;				// 유효종료일시(기간/일수구분 "P:기간"일 때 사용됨)
+    private int    availDays;				// 유효일수(기간/일수구분 "D:일수"일 때 사용됨)
+    private int    custPubLimitQty;		    // 고객당발행제한수량(0은 무제한)
+    private int    totPubLimitQty;			// 총발행제한수량(0은 무제한)
+    private int    onePubQty;				// 1회발행수량(기본은 1)
+    private String dnGb;					// 다운로드구분(공통코드G058)
+    private String downStdt;				// 다운로드시작일시
+    private String downEddt;			    // 다운로드종료일시
+    private int    buyLimitAmt;			    // 구매제한금액(0은 제한없음. 그 외는 00 이상 구매 시 사용)
+    private int    planSq;					// 기획전번호(쿠폰유형이 플러스쿠폰 일 때 사용 기획전번호)
+    private String reissuance;				// 쿠폰재발급여부(공통코드G231)
+    private String cpnStat;				    // 쿠폰상태(공통코드G232)
+    private String endAlimYn;				// 만료알림여부
+    private String firstYn;				    // 첫구매여부 (Y:구매이력이없음 | N:구매이력있음)
+    private String downYn;					// 다운로드가능여부(마이페이지, 상품상세) --> EP쿠폰, 난수쿠폰
+    private String custJoinStdt;			// 회원가입일자(FROM) 20200101 (신규회원여부의 판단을 가입일자로 설정함)
+    private String custJoinEddt;			// 회원가입일자(FROM) 20200101 (신규회원여부의 판단을 가입일자로 설정함)
+    private String buyStdt;				    // 회원가입일자(FROM) 20200101 (구매기간일자(FROM) (해당기간에 구매이력이 없으면 다운로드 가능))
+    private String buyEddt;				    // 구매기간일자(TO)
+    private int    issueCnt;				// 쿠폰발급개수
+    private int    useCnt;					// 쿠폰사용개수
+    private String payType;                 // 결제수단
+    private String custJoinYn;              // 신규회원여부
+    private String afChannel;               // 제휴링크
+    private String dcCdGb;                  // 할인코드유형 (공통코드G233)
+    private String rdCpnNm;                 // 랜덤쿠폰 사용키 (시리얼명 or 난수)
 
     // 그리드 파라미터
-    private String  supplyCompList;         // 공급업체 리스트
-    private String  brandList;              // 브랜드 리스트
-    private String  applyGoodsList;         // 적용상품 리스트
-    private String  exceptGoodsList;        // 제외상품 리스트
-    private String  cateList;               // 카테고리 리스트
-    private String  burdenList;             // 업체 분담율 리스트
+    private String supplyCompList;          // 공급업체 리스트
+    private String brandList;               // 브랜드 리스트
+    private String applyGoodsList;          // 적용상품 리스트
+    private String exceptGoodsList;         // 제외상품 리스트
+    private String cateList;                // 카테고리 리스트
+    private String burdenList;              // 업체 분담율 리스트
 
     // TB_COUPON_BAN_GOODS
-    private Integer  cpnBanGoodsSq;         //  제외상품시퀀스
+    private int    cpnBanGoodsSq;           //  제외상품시퀀스
 
     // Pagination
     private TscPageRequest pageable;

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

@@ -374,6 +374,8 @@ public class Order extends TscBaseDomain {
 	private String rtnLocDtlAddr;
 	private String rtnLocTelno;
 	private String rtnLocNm;
+	private int exchangeOrdDtlNo;
+	private int exchangeOrdDtlItemSq;
 }
 
 

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

@@ -618,7 +618,7 @@
 
 	<!-- 특정 쿠폰 발급받은 회원 조회-->
 	<select id="getSerialOverlapCheck" parameterType="Coupon" resultType="int">
-		/* TsaCoupon.getSerialOverlapCheck : 중복 시리얼넘버 체크 */
+		/* TsaCoupon.getSerialOverlapCheck : 기간 내 중복 시리얼넘버 체크 */
 		WITH CHECK_DATA AS (
 		    SELECT C.CPN_ID
 				 , C.DOWN_STDT
@@ -646,30 +646,15 @@
 				WHERE 1=1
 				AND C.DOWN_EDDT >= STR_TO_DATE(#{downStdt}, '%Y-%m-%d %H:%i:%s')
 				AND C.DOWN_EDDT <![CDATA[ <= ]]> STR_TO_DATE(#{downEddt}, '%Y-%m-%d %H:%i:%s')
-				UNION
-				SELECT COUNT(1) AS CNT		<!-- 유효 시작일이 겹치는 쿠폰번호 찾기 -->
-				FROM CHECK_DATA C
-				WHERE 1=1
-				AND C.AVAIL_STDT >= STR_TO_DATE(#{downStdt}, '%Y-%m-%d %H:%i:%s')
-				AND C.AVAIL_STDT <![CDATA[ <= ]]> STR_TO_DATE(#{downEddt}, '%Y-%m-%d %H:%i:%s')
-				UNION
-				SELECT COUNT(1) AS CNT		<!-- 유효 종료일이 겹치는 쿠폰번호 찾기 -->
-				FROM CHECK_DATA C
-				WHERE 1=1
-				AND C.AVAIL_EDDT >= STR_TO_DATE(#{downStdt}, '%Y-%m-%d %H:%i:%s')
-				AND C.AVAIL_EDDT <![CDATA[ <= ]]> STR_TO_DATE(#{downEddt}, '%Y-%m-%d %H:%i:%s')
-				UNION
-				SELECT COUNT(1) AS CNT		<!-- 쿠폰 사용 기한이 일수일경우 다운시작일 + 일수가 사용가능일. 해당 기준으로 겹치는 쿠폰번호 찾기 -->
-				FROM CHECK_DATA C
-				WHERE 1=1
-				AND DATE_ADD(C.DOWN_STDT, INTERVAL C.AVAIL_DAYS DAY) >= STR_TO_DATE(#{downStdt}, '%Y-%m-%d %H:%i:%s')
-				AND DATE_ADD(C.DOWN_STDT, INTERVAL C.AVAIL_DAYS DAY) <![CDATA[ <= ]]> STR_TO_DATE(#{downEddt}, '%Y-%m-%d %H:%i:%s')
-				UNION
-				SELECT COUNT(1) AS CNT		<!-- 쿠폰 사용 기한이 일수일경우 다운종료일 + 일수가 사용종료일. 해당 기준으로 겹치는 쿠폰번호 찾기 -->
-				FROM CHECK_DATA C
-				WHERE 1=1
-				AND DATE_ADD(C.DOWN_EDDT, INTERVAL C.AVAIL_DAYS DAY) >= STR_TO_DATE(#{downStdt}, '%Y-%m-%d %H:%i:%s')
-				AND DATE_ADD(C.DOWN_EDDT, INTERVAL C.AVAIL_DAYS DAY) <![CDATA[ <= ]]> STR_TO_DATE(#{downEddt}, '%Y-%m-%d %H:%i:%s') ) A
+		      ) A
+	</select>
+
+	<!-- 특정 쿠폰 발급받은 회원 조회-->
+	<select id="getRandomCouponNmCnt" parameterType="String" resultType="int">
+		/* TsaCoupon.getRandomCouponNmCnt : 중복 시리얼넘버 체크 */
+		SELECT COUNT(1) AS CNT
+		FROM TB_RANDOM_COUPON
+		WHERE RD_CPN_NM = #{value}
 	</select>
 
 	<!-- 고객 쿠폰 발행 -->

+ 32 - 15
src/main/java/com/style24/persistence/mybatis/shop/TsaCustomer.xml

@@ -372,25 +372,26 @@
 		/* TsaCustomer.getCustomerPoint */
 		SELECT IFNULL((
 		               SELECT SUM(RM_PNT_AMT)
-		               FROM  TB_CUST_POINT
-		               WHERE CUST_NO = C.CUST_NO
-		               AND   EXP_CMP_DT IS NULL
+		               FROM   TB_CUST_POINT
+		               WHERE  CUST_NO = C.CUST_NO
+		               AND    EXP_CMP_DT IS NULL
+		               AND    EXP_BE_DT > NOW()
 		               ), 0)                           AS RM_PNT_AMT -- 가용포인트
 		     , IFNULL((
-		                SELECT SUM(GV_PNT_AMT)
-		                FROM   TB_CUST_POINT
-		                WHERE  CUST_NO = C.CUST_NO
+		               SELECT SUM(GV_PNT_AMT)
+		               FROM   TB_CUST_POINT
+		               WHERE  CUST_NO = C.CUST_NO
 		               ), 0)                           AS GV_PNT_AMT -- 누적포인트
 		     , IFNULL((
-		                SELECT SUM(US_PNT_AMT)
-		                FROM  TB_CUST_POINT
-		                WHERE CUST_NO = C.CUST_NO
+		               SELECT SUM(US_PNT_AMT)
+		               FROM   TB_CUST_POINT
+		               WHERE  CUST_NO = C.CUST_NO
 		               ), 0)                           AS US_PNT_AMT -- 사용포인트
 		     , IFNULL((
-		                SELECT SUM(RM_PNT_AMT)
-		                FROM  TB_CUST_POINT
-		                WHERE CUST_NO = C.CUST_NO
-		                AND   EXP_CMP_DT IS NOT NULL
+		               SELECT SUM(RM_PNT_AMT)
+		               FROM   TB_CUST_POINT
+		               WHERE  CUST_NO = C.CUST_NO
+		               AND    (EXP_CMP_DT IS NOT NULL OR EXP_BE_DT <![CDATA[<]]> NOW())
 		               ), 0)                           AS EXPIRE_PNT_AMT -- 소멸포인트
 		     , IFNULL((
 		               SELECT SUM(A.PNT_AMT + B.PNT_AMT) AS PNT_AMT
@@ -440,9 +441,25 @@
 		           , 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
+		           , 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
+		           , 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

+ 88 - 1
src/main/java/com/style24/persistence/mybatis/shop/TsaDsiplay.xml

@@ -979,7 +979,7 @@
 			FROM TB_GOODS G
 			, (SELECT SEARCH_CD, MIN(DISP_ORD) AS TMP_DISP_ORD
 			FROM TB_SEARCH_DATA
-			WHERE REG_ID = #{regId}
+			WHERE REG_NO = #{regNo}
 			GROUP BY SEARCH_CD
 			) D
 			WHERE G.GOODS_CD LIKE D.SEARCH_CD||'%'
@@ -988,4 +988,91 @@
 		</if>
 		WHERE A.GOODS_CD = G.GOODS_CD
 	</select>
+
+	<select id="getCategoryGoodsList" parameterType="CategoryGoods" resultType="CategoryGoods">
+		/* TsaDisplay.getCategoryGoodsList */
+		SELECT Z.*
+		FROM ( SELECT @rownum := @rownum + 1 AS RNUM
+					, A.*
+			   FROM ( SELECT G.GOODS_CD
+						   , G.GOODS_TNM
+						   , G.GOODS_NM
+						   , A.CATE_NO
+						   , A.DISP_ORD
+						   , G.GOODS_TYPE
+						   , G.TAG_PRICE
+						   , G.LIST_PRICE
+						   , G.CURR_PRICE
+						   , G.DC_RATE
+						   , G.GOODS_STAT
+						   , G.BRAND_CD
+						   , A.REG_NO
+						   , A.REG_DT
+						   , G.SUPPLY_GOODS_CD
+						   , G.STYLE_YEAR
+						   , NVL(G.FORMAL_GB,'10') AS FORMAL_GB
+					   FROM ( SELECT A.GOODS_CD
+								   , A.CATE_NO
+								   , A.DISP_ORD
+								   , A.REG_NO
+								   , A.REG_DT
+							   FROM TB_CATE_GOODS A
+							   WHERE 1=1
+								<if test='selLvl == "3"'>
+									AND CATE_NO  = #{cate1No}
+								</if>
+								<if test='selLvl == "4"'>
+									AND CATE_NO  = #{cate2No}
+								</if>
+								<if test='selLvl == "5"'>
+									AND CATE_NO  = #{cate3No}
+								</if>
+								<if test='selLvl == "6"'>
+									AND CATE_NO  = #{cate4No}
+								</if>
+							   AND EXISTS (   SELECT 1
+											   FROM TB_CATE_4SRCH
+											   WHERE 1=1
+												<if test='selLvl == "3"'>
+													AND CATE1_NO  = A.CATE_NO
+												</if>
+												<if test='selLvl != "3"'>
+													AND CATE1_NO  = #{cate1No}
+													<if test='selLvl == "4"'>
+														AND CATE2_NO  = A.CATE_NO
+													</if>
+													<if test='selLvl != "4"'>
+														AND CATE2_NO  = #{cate2No}
+														<if test='selLvl == "5"'>
+															AND CATE3_NO  = A.CATE_NO
+														</if>
+														<if test='selLvl == "6"'>
+															AND CATE3_NO  = #{cate3No}
+															AND CATE4_NO  = A.CATE_NO
+														</if>
+													</if>
+												</if>
+											)
+							   ) A
+						<if test="searchGb == null or searchGb =='BASIC'">
+							, TB_GOODS G
+						</if>
+						<if test="searchGb != null and searchGb =='EXCEL'">
+							, (SELECT G.*
+							, TMP_DISP_ORD
+							FROM TB_GOODS G
+							, (SELECT SEARCH_CD, MIN(DISP_ORD) AS TMP_DISP_ORD
+							FROM TB_SEARCH_DATA
+							WHERE REG_NO = #{regNo}
+							GROUP BY SEARCH_CD
+							) D
+							WHERE G.GOODS_CD LIKE D.SEARCH_CD||'%'
+							OR G.SUPPLY_GOODS_CD LIKE D.SEARCH_CD||'%'
+							) G
+						</if>
+					   JOIN ( SELECT @rownum := 0) R
+					   WHERE A.GOODS_CD = G.GOODS_CD
+					   ORDER BY A.DISP_ORD ASC, G.UPD_DT DESC, G.CURR_PRICE DESC, G.GOODS_CD ASC
+			<include refid="getListPagingCondition_sql"/>
+	</select>
 </mapper>

+ 77 - 24
src/main/java/com/style24/persistence/mybatis/shop/TsaFreegiftPromotion.xml

@@ -4,41 +4,94 @@
 	<!-- 사은품 프로모션 리스트 조회 -->
 	<select id="getFreeGoodsPromotionList" parameterType="FreeGoodsPromotion" resultType="FreeGoodsPromotion">
 		/* TsaMarketing.getFreeGoodsPromotionList :  사은품 프로모션 리스트 조회 */
-		SELECT FG.FREEGIFT_SQ
-			 , FG.FREEGIFT_NM
-			 , FG.FREEGIFT_STAT
-		     , (SELECT CD_NM FROM TB_COMMON_CODE WHERE CD = FG.FREEGIFT_STAT) AS FREEGIFT_STAT_NM
-		     , FG.SELF_YN
-			 , DATE_FORMAT(FG.FREEGIFT_STDT, '%Y.%m.%d') AS FREEGIFT_STDT
-			 , DATE_FORMAT(FG.FREEGIFT_EDDT, '%Y.%m.%d') AS FREEGIFT_EDDT
-			 , (SELECT USER_NM FROM TB_USER WHERE USER_NO = FG.REG_NO) AS REG_NM
-			 , DATE_FORMAT(FG.REG_DT, '%Y.%m.%d %H:%i:%S') AS REG_DT
-			 , (SELECT USER_NM FROM TB_USER WHERE USER_NO = FG.UPD_NO) AS UPD_NM
-			 , DATE_FORMAT(FG.UPD_DT, '%Y.%m.%d %H:%i:%S') AS UPD_DT
-		  FROM TB_FREEGIFT FG
-		 WHERE 1=1
-		   AND DEL_YN = 'N'
+		SELECT Z.*
+		FROM (SELECT @rownum := @rownum + 1 AS RNUM
+				   , A.*
+				FROM (  SELECT FG.FREEGIFT_SQ
+							 , FG.FREEGIFT_NM
+							 , FG.FREEGIFT_STAT
+							 , (SELECT CD_NM FROM TB_COMMON_CODE WHERE CD = FG.FREEGIFT_STAT) AS FREEGIFT_STAT_NM
+							 , FG.SELF_YN
+							 , DATE_FORMAT(FG.FREEGIFT_STDT, '%Y.%m.%d') AS FREEGIFT_STDT
+							 , DATE_FORMAT(FG.FREEGIFT_EDDT, '%Y.%m.%d') AS FREEGIFT_EDDT
+							 , (SELECT USER_NM FROM TB_USER WHERE USER_NO = FG.REG_NO) AS REG_NM
+							 , DATE_FORMAT(FG.REG_DT, '%Y.%m.%d %H:%i:%S') AS REG_DT
+							 , (SELECT USER_NM FROM TB_USER WHERE USER_NO = FG.UPD_NO) AS UPD_NM
+							 , DATE_FORMAT(FG.UPD_DT, '%Y.%m.%d %H:%i:%S') AS UPD_DT
+						  FROM TB_FREEGIFT FG
+						 WHERE 1=1
+						   AND DEL_YN = 'N'
+						<if test="searchTxt != null and searchTxt != ''">
+							<if test="promotionGubun != null and promotionGubun == 'freegiftSq'">
+						   AND FG.FREEGIFT_SQ = #{searchTxt}
+							</if>
+							<if test="promotionGubun != null and promotionGubun == 'freegiftNm'">
+						   AND FG.FREEGIFT_NM = #{searchTxt}
+							</if>
+						</if>
+						/* 프로모션ID로 검색하면 기간보다 우선하여 검색한다 */
+						<if test="searchTxt == '' or promotionGubun != 'freegiftSq'">
+							<if test="stDate != null and stDate != ''">
+								<if test="edDate != null and edDate != ''">
+							   AND FREEGIFT_STDT BETWEEN STR_TO_DATE(#{stDate},'%Y-%m-%d%H%i%S') AND STR_TO_DATE(CONCAT(#{edDate}, '235959'),'%Y-%m-%d%H%i%S')
+							   AND FREEGIFT_EDDT BETWEEN STR_TO_DATE(#{stDate},'%Y-%m-%d%H%i%S') AND STR_TO_DATE(CONCAT(#{edDate}, '235959'),'%Y-%m-%d%H%i%S')
+								</if>
+							</if>
+						</if>
+				 	 ) A
+				JOIN (SELECT @rownum := 0) R
+				ORDER BY REG_DT DESC
+				) Z
+		WHERE  1=1
+		AND    Z.RNUM BETWEEN  #{pageable.startRow} AND #{pageable.endRow}
+	</select>
+
+	<!-- 사은품 프로모션 리스트 Count 조회 -->
+	<select id="getFreeGoodsPromotionListCount" parameterType="FreeGoodsPromotion" resultType="int">
+		/* TsaMarketing.getFreeGoodsPromotionListCount :  사은품 프로모션 리스트 조회 */
+		SELECT COUNT(1) AS CNT
+		FROM TB_FREEGIFT FG
+		WHERE 1=1
+		AND DEL_YN = 'N'
 		<if test="searchTxt != null and searchTxt != ''">
 			<if test="promotionGubun != null and promotionGubun == 'freegiftSq'">
-		   AND FG.FREEGIFT_SQ = #{searchTxt}
+				AND FG.FREEGIFT_SQ = #{searchTxt}
 			</if>
 			<if test="promotionGubun != null and promotionGubun == 'freegiftNm'">
-		   AND FG.FREEGIFT_NM = #{searchTxt}
+				AND FG.FREEGIFT_NM = #{searchTxt}
 			</if>
 		</if>
 		/* 프로모션ID로 검색하면 기간보다 우선하여 검색한다 */
 		<if test="searchTxt == '' or promotionGubun != 'freegiftSq'">
 			<if test="stDate != null and stDate != ''">
 				<if test="edDate != null and edDate != ''">
-			   AND FREEGIFT_STDT BETWEEN STR_TO_DATE(#{stDate},'%Y-%m-%d%H%i%S') AND STR_TO_DATE(CONCAT(#{edDate}, '235959'),'%Y-%m-%d%H%i%S')
-			   AND FREEGIFT_EDDT BETWEEN STR_TO_DATE(#{stDate},'%Y-%m-%d%H%i%S') AND STR_TO_DATE(CONCAT(#{edDate}, '235959'),'%Y-%m-%d%H%i%S')
+					AND FREEGIFT_STDT BETWEEN STR_TO_DATE(#{stDate},'%Y-%m-%d%H%i%S') AND STR_TO_DATE(CONCAT(#{edDate}, '235959'),'%Y-%m-%d%H%i%S')
+					AND FREEGIFT_EDDT BETWEEN STR_TO_DATE(#{stDate},'%Y-%m-%d%H%i%S') AND STR_TO_DATE(CONCAT(#{edDate}, '235959'),'%Y-%m-%d%H%i%S')
 				</if>
 			</if>
 		</if>
+	</select>
+
+	<!-- 사은품 프로모션 조회 -->
+	<select id="getFreeGoodsPromotionInfo" parameterType="FreeGoodsPromotion" resultType="FreeGoodsPromotion">
+		/* TsaMarketing.getFreeGoodsPromotionInfo :  사은품 프로모션 조회 */
+		SELECT FG.FREEGIFT_SQ
+			 , FG.FREEGIFT_NM
+			 , FG.FREEGIFT_STAT
+			 , (SELECT CD_NM FROM TB_COMMON_CODE WHERE CD = FG.FREEGIFT_STAT) AS FREEGIFT_STAT_NM
+			 , FG.SELF_YN
+			 , DATE_FORMAT(FG.FREEGIFT_STDT, '%Y-%m-%d %H:%i:%S') AS FREEGIFT_STDT
+			 , DATE_FORMAT(FG.FREEGIFT_EDDT, '%Y-%m-%d %H:%i:%S') AS FREEGIFT_EDDT
+			 , (SELECT USER_NM FROM TB_USER WHERE USER_NO = FG.REG_NO) AS REG_NM
+			 , DATE_FORMAT(FG.REG_DT, '%Y.%m.%d %H:%i:%S') AS REG_DT
+			 , (SELECT USER_NM FROM TB_USER WHERE USER_NO = FG.UPD_NO) AS UPD_NM
+			 , DATE_FORMAT(FG.UPD_DT, '%Y.%m.%d %H:%i:%S') AS UPD_DT
+		FROM TB_FREEGIFT FG
+		WHERE 1=1
+		AND DEL_YN = 'N'
 		<if test="freegiftSq != null and freegiftSq != ''">
-		   AND FG.FREEGIFT_SQ = #{freegiftSq}
+			AND FG.FREEGIFT_SQ = #{freegiftSq}
 		</if>
-		 ORDER BY REG_DT DESC
 	</select>
 
 	<!-- 사은품 프로모션 제휴몰 리스트 조회 -->
@@ -195,8 +248,8 @@
 		) VALUES (
 			  #{freegiftNm}
 			, #{freegiftStat}
-			, STR_TO_DATE(#{freegiftStdt},'%Y%m%d%H%i%S')
-			, STR_TO_DATE(CONCAT(#{freegiftEddt}, '235959'),'%Y%m%d%H%i%S')
+			, STR_TO_DATE(#{freegiftStdt},'%Y-%m-%d %H:%i:%S')
+			, STR_TO_DATE(#{freegiftEddt},'%Y-%m-%d %H:%i:%S')
 			, #{selfYn}
 			, #{allYn}
 			, #{regNo}
@@ -311,8 +364,8 @@
 	<update id="updateFreegoodsPromotionInfo" parameterType="FreeGoodsPromotion">
 		/* TsaMarketing.updateFreegoodsPromotionInfo : 사은품 프로모션 마스터 정보 수정 */
 		UPDATE TB_FREEGIFT
-        SET FREEGIFT_STDT = STR_TO_DATE(#{freegiftStdt},'%Y%m%d%H%i%S')
-          , FREEGIFT_EDDT = STR_TO_DATE(CONCAT(#{freegiftEddt}, '235959'),'%Y%m%d%H%i%S')
+        SET FREEGIFT_STDT = STR_TO_DATE(#{freegiftStdt},'%Y-%m-%d %H:%i:%S')
+          , FREEGIFT_EDDT = STR_TO_DATE(#{freegiftEddt},'%Y-%m-%d %H:%i:%S')
           , FREEGIFT_NM = #{freegiftNm}
 		  , SELF_YN = #{selfYn}
 		  , ALL_YN = #{allYn}

+ 18 - 3
src/main/webapp/WEB-INF/views/customer/CustomerDetailForm.html

@@ -709,13 +709,25 @@
 			}
 		},
 		{
-			headerName: "포인트사유", field: "occurGb", width: 300, cellClass: 'text-center',
+			headerName: "포인트사유", field: "occurGb", width: 100, cellClass: 'text-center',
 			valueFormatter: function (params) {
 				return gagaAgGrid.lookupValue(pntOccurGbList, params.value);
 			}
 		},
 		{headerName: "포인트상세사유", field: "occurDtlDesc", width: 300, cellClass: 'text-center'},
-		{headerName: "등록자", field: "regNo", width: 100, cellClass: 'text-center'}
+		{
+			headerName: "만료예정일시", field: "expBeDt", width: 150, cellClass: 'text-center',
+			cellRenderer: function (params) {
+				return gagaAgGrid.toDateTimeFormat(params.value);
+			}
+		},
+		{
+			headerName: "만료완료일시", field: "expCmpDt", width: 150, cellClass: 'text-center',
+			cellRenderer: function (params) {
+				return gagaAgGrid.toDateTimeFormat(params.value);
+			}
+		},
+		{headerName: "등록자", field: "regNm", width: 100, cellClass: 'text-center'}
 	];
 
 	//상품권내역 그리드
@@ -1078,7 +1090,10 @@
 
 	// 포인트부여 버튼
 	$('#btnCustPointCreate').on('click', function () {
-		cfnGrantPointPopup();
+		let elementCustNo ='#custInfoForm input[name=custNo]';
+		const actionUrl = '/marketing/point/grant/popup/form?elementCustNo=' + encodeURIComponent(elementCustNo);
+
+		cfnOpenModalPopup(actionUrl, 'popupPointGrantForm');
 	});
 
 	// 쿠폰발급 버튼

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

@@ -33,19 +33,19 @@
 						</colgroup>
 						<tbody>
 						<tr >
-							<th>수신자번호 <em class="star"></em></th>
+							<th>수신자번호<em class="required" title="필수"></em></th>
 							<td>
 								<input type="text" class="w150" name="cellPhnno" data-valid-name="수신번호"  required="required"  maxlength="13"/>
 							</td>
 						</tr>
 						<tr>
-							<th>발신자번호<em class="star"></em></th>
+							<th>발신자번호<em class="required" title="필수"></em></th>
 							<td>
 								<input type="text" class="w150" name="callBack" th:value="${callBack}" maxlength="11" readonly="readonly"/>
 							</td>
 						</tr>
 						<tr>
-							<th>메시지<em class="star"></em></th>
+							<th>메시지<em class="required" title="필수"></em></th>
 							<td>
 								<textarea class="textareaR4"  style="resize: none;" name ="content" ></textarea>
 								<span name="count">0</span> / 2000 byte

+ 94 - 102
src/main/webapp/WEB-INF/views/display/CategoryGoodsForm.html

@@ -26,8 +26,9 @@
 	<!-- //메뉴 설명 -->
 
 	<!-- 검색조건 영역 -->
-	<div class="panelStyle">
-		<form id="searchForm" name="searchForm" action="#" th:action="@{'/display/category/list'}" onsubmit="$('#btnSearch').trigger('click'); return false;">
+	<form id="searchForm" name="searchForm" action="#" th:action="@{'/display/category/goods/list'}" onsubmit="$('#btnSearch').trigger('click'); return false;">
+		<div class="panelStyle">
+			<input type="hidden" id="searchGb" name="searchGb" />
 			<table class="frmStyle" aria-describedby="검색조건">
 				<colgroup>
 					<col width="10%"/>
@@ -60,35 +61,71 @@
 					</td>
 				</tr>
 			</table>
-		</form>
-	</div>
+		</div>
 	<!-- 검색조건 영역 -->
 
-	<!-- 리스트 영역 -->
+	<!-- 패널 영역1 -->
 	<div class="panelStyle">
-		<div id="gridList" style="width: 100%; height: 470px" class="ag-theme-balham"></div>
+		<!-- 상단버튼 영역  -->
+		<ul class="panelBar">
+			<li>
+				<span id="goodsSearch" class="btnLeft" style="display:none">
+					<span style="padding:5.5px 15px; background:#d8eafc !important; border-top:1px solid #ddd; border-bottom:0.5px solid #dae0fd; font-weight: bold;">상품코드</span>
+					<input type="text" class="w100" name="goodsCd" id="goodsCd" />
+					<button type="button" class="btn btn-base btn-lg" id="btnSearch">조회</button>
+					<button type="button" class="btn btn-default btn-lg" onclick="cfnDownloadSampleFile('SF003');">엑셀조회 양식 다운로드</button>
+					<button type="button" class="btn btn-base btn-lg" id="btnExcelSearch">엑셀조회</button>
+				</span>
+			</li>
+			<li class="right">
+				검색결과 : <strong><span id="gridRowTotalCount">0</span> 건</strong>&nbsp;
+				쪽번호 <span id="pgNo">0</span>/ <strong id="endPgNo">0</strong>&nbsp;&nbsp;
+				<select id="pageSize" name="pageSize">
+					<option value="50" selected="selected">50개씩 보기</option>
+					<option value="100">100개씩 보기</option>
+					<option value="500">500개씩 보기</option>
+					<option value="1000">1000개씩 보기</option>
+				</select>
+				<input type="hidden" name="pageNo" id="pageNo" value ="1"/>
+			</li>
+		</ul>
+		<!-- 검색결과 영역 -->
+		<!--<div id="gridList" style="width: 100%; height: 700px;" class="ag-theme-balham lh60"></div>-->
+		<div id="gridList" style="width: 100%; height: 570px" class="ag-theme-balham"></div>
+		<ul class="panelBar">
+			<li class="center">
+				<div class="tablePaging" id="categoryGoodsListPagination"></div>
+			</li>
+		</ul>
+		<ul class="panelBar">
+			<li class="aR" id="btnGoodsEdit" style="display:none">
+				<button type="button" class="btn btn-primary btn-lg leafCateBtn" id="btnAddGoods">상품추가</button>
+				<!-- <button type="button" class="btn btn-primary btn-lg" id="btnDispChange">순서변경</button>
+                <button type="button" class="btn btn-primary btn-lg" id="btnSelectTop">선택최상위로</button> -->
+				<button type="button" class="btn btn-danger btn-lg" id="btnSelectDel">선택삭제</button>
+			</li>
+		</ul>
 	</div>
-	<!-- //리스트 영역 -->
 
-	<!-- 등록/수정 -->
-	<div class="panelStyle">
-		<form id="detailForm" name="detailForm" action="#" th:action="@{'/display/category/save'}">
+	<!-- 상품이동/복사 -->
+	<div class="panelStyle" id="addCategory" style="display:none">
+		<form id="saveForm" name="saveForm" action="#" th:action="@{'/display/goods/category/save'}">
 
 		</form>
 
 		<!-- 버튼 배치 영역 -->
 		<ul class="panelBar">
 			<li class="right">
-				<button type="button" class="btn btn-info btn-lg" id="btnNew">신규</button>
-				<button type="button" class="btn btn-success btn-lg" id="btnSave">저장</button>
-				<!--<button type="button" class="btn btn-base btn-lg" id="btnRefresh4Srch" th:if="${sessionInfo.roleCd == 'G001_0000'}">4SRCH 갱신</button>-->
+				<button type="button" class="btn btn-primary btn-lg leafCateBtn" id="btnMoveGoods">상품이동</button>
+				<button type="button" class="btn btn-primary btn-lg leafCateBtn" id="btnCopyGoods">상품복사</button>
 			</li>
 		</ul>
 		<!-- //버튼 배치 영역 -->
 	</div>
-	<!-- 등록/수정 -->
+	<!-- 상품이동/복사 -->
+	</form>
 </div>
-
+<script type="text/javascript" src="/ux/plugins/gaga/gaga.paging.js?v=2019072202"></script>
 <script th:inline="javascript">
 	/*<![CDATA[*/
 	let siteList = gagajf.convertToArray([[${siteList}]]);
@@ -97,80 +134,32 @@
 	let formalGbList = gagajf.convertToArray([[${formalGbList}]]);
 	let conentsLocList = gagajf.convertToArray([[${conentsLocList}]]);
 
-	let columnDefs = [
-		{
-			headerName: "사이트", field: "siteCd", width: 150, cellClass: 'text-center',
-			valueFormatter: function (params) { return gagaAgGrid.lookupValue(siteList, params.value); }
-		},
-		{
-			headerName: "카테고리구분", field: "cateGb", width: 150, cellClass: 'text-center',
-			cellRenderer: function (params) { return gagaAgGrid.lookupValue(cateGbList, params.value); }
-		},
-		{headerName: "카테고리번호", field: "cateNo", width: 150, cellClass: 'text-center'},
-		{
-			headerName: "카테고리명", field: "cateNm", width: 150, cellClass: 'text-center',
-			cellRenderer: function(params) {
-				return '<a href="javascript:void(0);">' + params.value + '</a>';
-			}
-		},
-		{
-			headerName: "카테고리유형", field: "cateType", width: 150, cellClass: 'text-center',
-			cellRenderer: function (params) { return gagaAgGrid.lookupValue(cateTypeList, params.value); }
-		},
-		{headerName: "말단여부", field: "leafYn", width: 80, cellClass: 'text-center'},
-		{headerName: "노출순서", field: "dispOrd", width: 100, cellClass: 'text-center'},
-		{
-			headerName: "정상이월구분", field: "formalGb", width: 150, cellClass: 'text-center',
-			cellRenderer: function (params) { return gagaAgGrid.lookupValue(formalGbList, params.value); }
-		},
-		{
-			headerName: "컨텐츠위치", field: "contentsLoc", width: 200, cellClass: 'text-center',
-			cellRenderer: function (params) { return gagaAgGrid.lookupValue(conentsLocList, params.value); }
-		},
-		{headerName: "노출여부", field: "dispYn", width: 80, cellClass: 'text-center'},
-		{headerName: "사용여부", field: "useYn", width: 80, cellClass: 'text-center'}
+	let columnDefs1 = [
+		{width: 40, minWidth: 40, cellClass: 'text-center', 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: "goodsCd", width: 150, cellClass: 'text-center'},
+		{headerName: "상품타이틀명", field: "goodsTnm", width: 150, cellClass: 'text-center'},
+		{headerName: "상품명", field: "goodsNm", width: 200, cellClass: 'text-center'},
+		{headerName: "카테고리번호", field: "cateNo", width: 120, cellClass: 'text-center'},
+		{headerName: "표시순서", field: "dispOrd", width: 80, cellClass: 'text-center'},
+		{headerName: "상품타입", field: "goodsType", width: 100, cellClass: 'text-center'},
+		{headerName: "TAG가", field: "tagPrice", width: 80, cellClass: 'text-center'},
+		{headerName: "정상가", field: "listPrice", width: 80, cellClass: 'text-center'},
+		{headerName: "현재판매가", field: "currPrice", width: 80, cellClass: 'text-center'},
+		{headerName: "할인율", field: "dcRate", width: 80, cellClass: 'text-center'},
+		{headerName: "상품상태", field: "goodsStat", width: 80, cellClass: 'text-center'},
+		{headerName: "브랜드코드", field: "brandCd", width: 80, cellClass: 'text-center'},
+		{headerName: "공급업체상품코드", field: "supplyGoodsCd", width: 80, cellClass: 'text-center'},
+		{headerName: "스타일구분", field: "styleYear", width: 80, cellClass: 'text-center'},
+		{headerName: "정상/이월", field: "formalGb", width: 80, cellClass: 'text-center'},
+		{headerName: "등록자", field: "regNo", width: 80, cellClass: 'text-center'},
+		{headerName: "등록일시", field: "regDt", width: 80, cellClass: 'text-center'}
 	];
 
-	let gridOptions = gagaAgGrid.getGridOptions(columnDefs);
-
-	// Cell click
-	gridOptions.onCellClicked = function(event) {
-		if (event.colDef.field != 'cateNm')
-			return;
-
-		$("#btnNew").click();
-		$('#detailForm input[name=siteCd]').val(event.data.siteCd);
-		$('#detailForm input[name=cateNo]').val(event.data.cateNo);
-		$('#detailForm input[name=cateNm]').val(event.data.cateNm);
-		$('#detailForm select[name=cateType]').val(event.data.cateType);
-
-		// 상위카테고리
-		var selLvl = $("#searchForm input[name=selLvl]").val();
-		for (let i = 1; i <= 5; i++) {
-			$("#cateLvl" + i).html($("#selCate" + i).html());
-			$("#cateLvl" + i).val($("#selCate" + i).val());
-			if (i >= selLvl) {
-				$("#cateLvl" + i).hide();
-			} else {
-				$("#cateLvl" + i).show();
-			}
-		}
-		$('#detailForm input[name=selLvl]').val(selLvl);
-
-		$('#detailForm input[name=dispOrd]').val(event.data.dispOrd);
-		$('#detailForm select[name=formalGb]').val(event.data.formalGb);
-		$('#detailForm select[name=contentsLoc]').val(event.data.contentsLoc);
-
-		// 카테고리유형에 따른 컨텐츠위치 설정 변경
-		if (event.data.cateType == 'G031_10') {
-			$('#detailForm select[name=contentsLoc]').prop('disabled', true);
-		} else if (event.data.cateType == 'G031_20') {
-			$('#detailForm select[name=contentsLoc]').prop('disabled', false);
-		}
-
-		$('#detailForm input:radio[name=dispYn]:input[value=' + event.data.dispYn + ']').click();
-		$('#detailForm input:radio[name=useYn]:input[value=' + event.data.useYn + ']').click();
-	}
+	let gridOptions = gagaAgGrid.getGridOptions(columnDefs1);
+	gridOptions.rowSelection = "multiple";
 
 	/**
 	 * 검색폼의 카테고리 선택 시
@@ -179,11 +168,14 @@
 		if (gagajf.isNull(val)) {
 			if (selLvl > 1) {
 				selLvl = selLvl - 1;
+				$("#goodsSearch").show();
+				$("#btnGoodsEdit").show();
 			} else {
 				selLvl = 1;
 			}
 		}
 		$('#searchForm input[name=selLvl]').val(selLvl);
+		$("#searchForm input[name=searchGb]").val("BASIC");
 
 		var data = { siteCd : 'G000_10'
 			, selLvl : selLvl
@@ -192,6 +184,7 @@
 			, cate2No : $('#searchForm select[name=cate2No]').val()
 			, cate3No : $('#searchForm select[name=cate3No]').val()
 			, cate4No : $('#searchForm select[name=cate4No]').val()
+			, searchGb : $("#searchForm input[name=searchGb]").val()
 		};
 
 		var jsonData = JSON.stringify(data);
@@ -215,27 +208,26 @@
 		}
 
 		$("#selCate" + selLvl).append(tag);
-		//$("#btnNew").click();
 
 		// 대카테고리 이상이면 상품 조회해서 그리드
-		if(selLvl > 1){
-			var data = { siteCd : 'G000_10'
-				, selLvl : selLvl
-				, cateGb : $('#searchForm select[name=cateGb]').val()
-				, cate1No : $('#searchForm select[name=cate1No]').val()
-				, cate2No : $('#searchForm select[name=cate2No]').val()
-				, cate3No : $('#searchForm select[name=cate3No]').val()
-				, cate4No : $('#searchForm select[name=cate4No]').val()
-			};
-
-			var jsonData = JSON.stringify(data);
-			gagajf.ajaxJsonSubmit('/display/category/goods/list', jsonData, fnCategoryGoodsListCallBack);
+		if(selLvl > 2){
+			$('#searchForm input[name=selLvl]').val(selLvl);
+			fnCategoryGoodsListSearch();
 		}
 	}
 
-	// 카테고리별 상품 조회하고 데이터 그리드
-	var fnCategoryGoodsListCallBack = function (data){
+	var fnCategoryGoodsListSearch = function(){
+		gagaPaging.init('searchForm', fnSearchCallBack, 'categoryGoodsListPagination', $('#searchForm').find('#pageSize').val());
+		gagaPaging.load(1);
+	}
 
+	var fnSearchCallBack = function(result){
+		$('#searchForm').find('#gridRowTotalCount').html(result.pageing.pageable.totalCount.addComma());
+		$('#searchForm').find('#pageNo').val(result.pageing.pageable.pageNo.addComma());
+		$('#searchForm').find('#pgNo').html(result.pageing.pageable.pageNo.addComma());
+		$('#searchForm').find('#endPgNo').html(result.pageing.pageable.totalPage.addComma());
+		gridOptions.api.setRowData(result.categoryGoodsList);
+		gagaPaging.createPagination(result.pageing.pageable);
 	}
 
 	// 신규

+ 1 - 1
src/main/webapp/WEB-INF/views/marketing/CouponListForm.html

@@ -225,7 +225,7 @@
 
 		// 쿠폰등록 팝업창
 		function fnCouponCreateForm(){
-			cfnCouponCreatePopup('');
+			cfnCouponCreatePopup('0');
 		}
 
 		// 초기화 클릭시

+ 53 - 6
src/main/webapp/WEB-INF/views/marketing/CouponPopupForm.html

@@ -78,15 +78,15 @@
 											</td>
 											<th class="randomCpnArea">난수생성수량<em class="required" title="필수"></em></th>
 											<td class="randomCpnArea">
-												<input type="text" name="randomCpnQty" class="w300" required="required" data-valid-name="랜덤쿠폰발급수량" data-valid-type="numeric">
+												<input type="text" name="randomCpnQty" class="w300" required="required" data-valid-name="난수생성수량" data-valid-type="numeric">
 											</td>
 										</tr>
 										<tr class="serialCpnArea" style="display:none;">
-											<th>시리얼<em class="required" title="필수"></em></th>
+											<th>시리얼쿠폰키워드<em class="required" title="필수"></em></th>
 											<td>
-												<input type="text" name="serialCpnNm" class="w300" required="required" data-valid-name="시리얼쿠폰키워드">
+												<input type="text" name="serialCpnNm" class="w300" maxlength="10" required="required" data-valid-name="시리얼쿠폰키워드">
 											</td>
-											<th>쿠폰발급수량<em class="required" title="필수"></em></th>
+											<th>시리얼쿠폰발급수량<em class="required" title="필수"></em></th>
 											<td>
 												<input type="text" name="serialCpnQty" class="w300" required="required" data-valid-name="시리얼쿠폰발급수량" data-valid-type="numeric">
 											</td>
@@ -618,7 +618,10 @@
 				if (!gagajf.validation('#CouponForm')) {
 					return false;
 				}
-				checkValidation();
+				// 데이터 validation 체크
+				if(!checkValidation()) {
+					return false;
+				}
 
 				gagajf.ajaxFormSubmit($('#CouponForm').prop('action'), '#CouponForm', function() {
 					uifnPopupClose('CouponRegForm');
@@ -644,7 +647,9 @@
 				if (!gagajf.validation('#CouponForm')) {
 					return false;
 				}
-				checkValidation();
+				if(!checkValidation()) {
+					return false;
+				}
 
 				gagajf.ajaxFormSubmit($('#CouponForm').prop('action'), '#CouponForm', function() {
 					uifnPopupClose('CouponRegForm');
@@ -728,6 +733,39 @@
 				return false;
 			}
 		}
+
+		// 할인쿠폰 유형에 따른 총 발행수량 수정 (주문서 쿠폰이고 난수쿠폰일 경우)
+		if($('#CouponForm #cpnType').val() == "G230_20" && $('#CouponForm input:radio[name="dcCdGb"]:checked').val() == "G233_20") {
+			if($("#CouponForm input[name=randomCpnQty]").val() == "" || $("#CouponForm input[name=randomCpnQty]").val() < 1) {
+				mcxDialog.alert('쿠폰의 발급 수량을 입력해주세요.');
+				$("#CouponForm input[name=randomCpnQty]").focus();
+				return false;
+			}
+			if($("#CouponForm input[name=randomCpnQty]").val() > 10000) {
+				mcxDialog.alert('쿠폰의 발급 수량은 10000장을 초과할 수 없습니다.');
+				$("#CouponForm input[name=randomCpnQty]").focus();
+				return false;
+			}
+
+		} else if ($('#CouponForm #cpnType').val() == "G230_20" && $('#CouponForm input:radio[name="dcCdGb"]:checked').val() == "G233_10") {		// 주문서 쿠폰이고 시리얼 유형일 경우
+			if($("#CouponForm input[name=serialCpnNm]").val().length > 10) {
+				mcxDialog.alert('시리얼쿠폰키워드는 10글자를 넘을 수 없습니다.');
+				$("#CouponForm input[name=serialCpnNm]").focus();
+				return false;
+			}
+			if($("#CouponForm input[name=serialCpnQty]").val() == "" || $("#CouponForm input[name=serialCpnQty]").val() < 1) {
+				mcxDialog.alert('쿠폰의 발급 수량을 입력해주세요.');
+				$("#CouponForm input[name=serialCpnQty]").focus();
+				return false;
+			}
+			if($("#CouponForm input[name=randomCpnQty]").val() > 10000) {
+				mcxDialog.alert('쿠폰의 발급 수량은 10000장을 초과할 수 없습니다.');
+				$("#CouponForm input[name=serialCpnQty]").focus();
+				return false;
+			}
+		}
+
+		return true;
 	}
 
 	// 할인방식 변경
@@ -786,15 +824,24 @@
 			$("#CouponForm .randomCpnArea").hide();
 			$("#CouponForm #custJoinYn").parent().attr("colspan", "");
 			$("#CouponForm .normalCol").attr("colspan", "5");
+			$('#CouponForm input[name="serialCpnNm"]').attr('required' , false);
+			$('#CouponForm input[name="serialCpnQty"]').attr('required' , false);
+			$('#CouponForm input[name="randomCpnQty"]').attr('required' , false);
 		} else {
 			if(this.value == "G233_10") {		// 시리얼 유형
 				$("#CouponForm .serialCpnArea").show();
 				$("#CouponForm .randomCpnArea").hide();
 				$("#CouponForm .normalCol").attr("colspan", "5");
+				$('#CouponForm input[name="serialCpnNm"]').attr('required' , true);
+				$('#CouponForm input[name="serialCpnQty"]').attr('required' , true);
+				$('#CouponForm input[name="randomCpnQty"]').attr('required' , false);
 			} else {							// 난수 유형
 				$("#CouponForm .serialCpnArea").hide();
 				$("#CouponForm .randomCpnArea").show();
 				$("#CouponForm .normalCol").attr("colspan", "");
+				$('#CouponForm input[name="serialCpnNm"]').attr('required' , false);
+				$('#CouponForm input[name="serialCpnQty"]').attr('required' , false);
+				$('#CouponForm input[name="randomCpnQty"]').attr('required' , true);
 			}
 			$("#CouponForm .dcCdCheck").hide();								// 총발행제한수량, 1회발행수량, 1인당발행제한수량 숨김
 			$("#CouponForm #custJoinYn").parent().attr("colspan", "5");		// 총발행제한 수량을 없애면서 신규회원여부 colspan 수정

+ 25 - 9
src/main/webapp/WEB-INF/views/marketing/FreeGoodsPromotionForm.html

@@ -46,7 +46,7 @@
 						</colgroup>
 
 						<tr>
-							<th>기간</th>
+							<th>기간<em class="required" title="필수"></em></th>
 							<td id="sellTerms"></td>
 						</tr>
 
@@ -87,8 +87,17 @@
 						<button type="button" class="btn btn-info btn-lg" id="btnFreeGoodsRegi" >프로모션등록</button>
 					</li>
 				</ul>
+
 				<!-- 검색결과 영역 -->
-				<div id="gridList" style="width: 100%; height: 700px;" class="ag-theme-balham"></div>
+				<div class="panelContent" style="overflow: hidden;">
+					<div id="gridList" style="width: 100%; height: 700px;" class="ag-theme-balham"></div>
+				</div>
+
+				<ul class="panelBar">
+					<li class="center">
+						<div class="tablePaging" id="freegiftPromotionListPagination"></div>
+					</li>
+				</ul>
 			</div>
 		</form>
 <script type="text/javascript" src="/ux/plugins/gaga/gaga.paging.js"></script>
@@ -155,7 +164,7 @@
 	var fnFreeGoodsPromotionListSearch = function() {
 		if(!fnConditionCheck()) return;
 
-		gagaPaging.init('searchForm', fnSearchCallBack, 'freeGoodsListPagination', $('#searchForm').find('#pageSize').val());
+		gagaPaging.init('searchForm', fnSearchCallBack, 'freegiftPromotionListPagination', $('#searchForm').find('#pageSize').val());
 		gagaPaging.load($("#searchForm input[name=pageNo]").val());
 	}
 
@@ -186,12 +195,10 @@
 			}
 
 			// 검색 기간 1년 이내로 지정
-			let stDateArray = fromDate.split("-");
-			let stDate = new Date(stDateArray[0], stDateArray[1] - 1, stDateArray[2]);
-			let edDateArray = toDate.split("-");
-			let edDate = new Date(edDateArray[0], edDateArray[1] - 1, edDateArray[2]);
-			let betweenDate = (edDate.getTime() - stDate.getTime()) / 1000 / 60 / 60 / 24;
-			if(betweenDate > 365) {
+			var sdt = new Date(fromDate);
+			var edt = new Date(toDate);
+			var dateDiff = Math.ceil((edt.getTime()-sdt.getTime())/(1000*3600*24));
+			if(dateDiff > 365) {
 				mcxDialog.alertC("최대 1년까지 선택하실 수 있습니다.", {
 					sureBtnText: "확인",
 					sureBtnClick: function() {
@@ -200,6 +207,15 @@
 				});
 				return false;
 			}
+		} else {
+			/* 기간 입력 확인 > 테스트 중에만 제거
+			mcxDialog.alertC("검색 기간을 입력해주세요.", {
+				sureBtnText: "확인",
+				sureBtnClick: function() {
+					$('#searchForm input[name=stDate]').focus();
+				}
+			});
+			return false;*/
 		}
 
 		return true;

+ 116 - 30
src/main/webapp/WEB-INF/views/marketing/FreeGoodsPromotionRegiForm.html

@@ -29,9 +29,9 @@
 					<table class="frmStyle">
 						<colgroup>
 							<col width="10%"/>
-							<col width="50%"/>
+							<col width="60%"/>
 							<col width="10%"/>
-							<col width="40%"/>
+							<col width="30%"/>
 						</colgroup>
 						<tr>
 							<th>프로모션명<em class="required" title="필수"></em></th>
@@ -46,14 +46,28 @@
 						<tr>
 							<th>행사 기간<em class="required" title="필수"></em></th>
 							<td>
-								<input type="text" class="schDate w100" id="freegiftStdt" name="freegiftStdt" maxlength="10" required="required" data-valid-name="시작일자"/>
+								<input type="hidden" id="freegiftStdt" name="freegiftStdt"/>
+								<input type="hidden" id="freegiftEddt" name="freegiftEddt"/>
+
+								<input type="text" class="schDate w100" id="freegiftStDate" name="freegiftStDate" maxlength="10" required="required" data-valid-name="시작일자"/>
+								<select name="freegiftStHH" id="freegiftStHH">
+									<option th:if="${hhList}" th:each="oneData , status : ${hhList}" th:text="${oneData.cdNm}" th:value="${oneData.cd}"></option>
+								</select>
+								<select name="freegiftStMM" id="freegiftStMM">
+									<option th:if="${mmList}" th:each="oneData , status : ${mmList}" th:text="${oneData.cdNm}" th:value="${oneData.cd}"></option>
+								</select>
 								~
-								<input type="text" class="schDate w100" id="freegiftEddt" name="freegiftEddt" maxlength="10" required="required" data-valid-name="종료일자"/>
+								<input type="text" class="schDate w100" id="freegiftEdDate" name="freegiftEdDate" maxlength="10" required="required" data-valid-name="종료일자"/>
+								<select name="freegiftEdHH" id="freegiftEdHH">
+									<option th:if="${hhList}" th:each="oneData , status : ${hhList}" th:text="${oneData.cdNm}" th:value="${oneData.cd}"></option>
+									<option th:text="24시" th:value="24"></option>
+								</select>
+								<select name="freegiftEdMM" id="freegiftEdMM">
+									<option th:if="${mmList}" th:each="oneData , status : ${mmList}" th:text="${oneData.cdNm}" th:value="${oneData.cd}"></option>
+								</select>
 							</td>
-							<!-- <td id="promotionTerms">수정시 행사기간 입력되도록 수정(JAVASCRIPT?) : before</td> -->
 							<th>상태</th>
 							<td>
-								<!-- 상태 입력 : before -->
 								<span name="freegiftStatText"></span>
 							</td>
 						</tr>
@@ -92,7 +106,6 @@
 								<tr>
 									<th>공급업체/브랜드</th>
 									<td>
-										<!-- 수정시 프로모션명 입력 : before -->
 										<div class="padding10" style="display:inline-block;width:49%;">
 											<span>공급업체 설정</span>
 											<div class="padding10 inner-tb-solid">
@@ -108,7 +121,6 @@
 												<button type="button" class="btn btnRight btn-success btn-lg" id="btnAddBrand">브랜드 추가</button>
 												<button type="button" class="btn btnRight btn-success btn-lg" id="btnDeleteBrand">선택삭제</button>
 												<br/>
-												<!-- 브랜드 선택 팝업(단수 선택 팝업... 복수를 새로 만들어야하는지 ? 아니면 변수처리해야하는지 ? -->
 												<div id="gridFGBrandList" style="width:100%; height:200px;" class="ag-theme-balham"></div>
 											</div>
 										</div>
@@ -249,13 +261,11 @@
 
 				<ul class="panelBar">
 					<li  class="right">
-						<!-- <th:block th:if="${sessionInfo.roleCd == 'G001_0000' OR sessionInfo.roleCd == 'G001_A000' OR sessionInfo.roleCd == 'G001_A101' OR sessionInfo.roleCd == 'G001_A100' OR sessionInfo.roleCd == 'G001_A001'}"> -->
 						<button type="button" class="btn btnRight btn-success btn-lg" id="btnSearchList">목록</button>
 						<button type="button" class="btn btnRight btn-success btn-lg fgButton" id="btnFreegoodsPromotionSave">저장</button>
 						<button type="button" class="btn btnRight btn-success btn-lg fgButton" id="btnChangeStatIng">진행</button>
 						<button type="button" class="btn btnRight btn-success btn-lg fgButton" id="btnPromotionDelete">삭제</button>
 						<button type="button" class="btn btnRight btn-success btn-lg fgButton" id="btnPromotionStop">중지</button>
-						<!-- </th:block> -->
 					</li>
 				</ul>
 			</form>
@@ -478,25 +488,48 @@
 				freegiftStatNm = "종료 (" + freegift.freegiftEddt + ")";
 			}
 
+			let stDtArr = freegift.freegiftStdt.split(" ");
+			let edDtArr = freegift.freegiftEddt.split(" ");
+
+			let stDate = stDtArr[0];
+			let stHour = stDtArr[1].split(":")[0];
+			let stMinute = stDtArr[1].split(":")[1];
+			let edDate = edDtArr[0];
+			let edHour = edDtArr[1].split(":")[0];
+			let edMinute = edDtArr[1].split(":")[1];
+
+			if(edDtArr[1] == "23:59:59") {
+				edHour = "24";
+				edMinute = "00";
+				$("#freeGoodsPromotionForm #freegiftEdMM option").hide();
+				$('#freeGoodsPromotionForm #freegiftEdMM option:first').show().prop("selected", true);
+			}
+
 			// 저장된 값 입력
 			$('#freeGoodsPromotionForm input[name=freegiftNm]').val(freegift.freegiftNm);
 			$('#freeGoodsPromotionForm span[name=freegiftSqText]').text(freegift.freegiftSq);
-			$('#freeGoodsPromotionForm input[name=freegiftStdt]').val(freegift.freegiftStdt.split(".").join("-"));
-			$('#freeGoodsPromotionForm input[name=freegiftEddt]').val(freegift.freegiftEddt.split(".").join("-"));
+			$('#freeGoodsPromotionForm input[name=freegiftStDate]').val(stDate);
+			$('#freeGoodsPromotionForm select[name=freegiftStHH]').val(stHour);
+			$('#freeGoodsPromotionForm select[name=freegiftStMM]').val(stMinute);
+			$('#freeGoodsPromotionForm input[name=freegiftEdDate]').val(edDate);
+			$('#freeGoodsPromotionForm select[name=freegiftEdHH]').val(edHour);
+			$('#freeGoodsPromotionForm select[name=freegiftEdMM]').val(edMinute);
 			$('#freeGoodsPromotionForm span[name=freegiftStatText]').text(freegiftStatNm);
 			$('#freeGoodsPromotionForm input[name=sectionVal]').val(freegift.sectionVal);
 			$('#freeGoodsPromotionForm input[name=sectionVal2]').val(freegift.sectionVal2);
 			$("#freeGoodsPromotionForm #regInfo").text(freegift.regNm + "(" + freegift.regDt + ")");
 			$("#freeGoodsPromotionForm #updInfo").text(freegift.updNm + "(" + freegift.updDt + ")");
+
 			// 자사 적용일 경우
 			if(freegift.selfYn == "Y") {
-				$("#freeGoodsPromotionForm input[name=selfYn]").addClass("checked");
+				$("#freeGoodsPromotionForm input[name=selfYn]").prop("checked", true);
 				$("#freeGoodsPromotionForm input[name=selfYn]").parent("label").addClass("checked");
 			}
 
 			// 외부몰 적용일 경우
 			if(freegift.extmallList != null && freegift.extmallList.length > 0) {
 				$("#freeGoodsPromotionForm input[name=extmallYn]").parent("label").addClass("checked");
+				$("#freeGoodsPromotionForm input[name=extmallYn]").prop("checked", true);
 				$("#freeGoodsPromotionForm #extmallCnt").text(freegift.extmallList.length);
 				$("#freeGoodsPromotionForm #allY").prop("checked", true);						// 제휴몰 선택시 지급 방법은 모두 지급으로 한정
 				$("#freeGoodsPromotionForm input[name=allYn]").prop("disabled", true);			// 제휴몰 선택시 지급 방법은 모두 지급에서 수정 불가
@@ -515,16 +548,35 @@
 				$("#freeGoodsPromotionForm #btnChangeStatIng").show();				// 진행
 				$("#freeGoodsPromotionForm #btnPromotionDelete").show();			// 삭제
 			} else {
-				// 진행 상태일 경우
-				if(freegift.freegiftStat == "G232_11") {
-					$("#freeGoodsPromotionForm #btnFreegoodsPromotionSave").show();	// 저장
-					$("#freeGoodsPromotionForm #btnPromotionStop").show();			// 중지
-
+				// 대기 상태일 경우를 제외하면 모든 상태 수정 불가(기획서대로 진행 상태에서 일부 수정 가능할 경우 if문 주석 제거)
+				//if(freegift.freegiftStat == "G232_11") {
 					// 진행 상태일 경우 기간, 적용대상상품, 추가제외상품 외 나머지 항목 수정 불가.
 					$("#freeGoodsPromotionForm input[name=extmallYn]").addClass("formControl");
 					$("#freeGoodsPromotionForm .disabledPoint").prop("disabled", true);
 					$("#freeGoodsPromotionForm .hideButten").hide();
-				}
+
+					// 진행 상태일 경우 전체 수정 불가(전체가 아닌 기획서대로면 아래 내용만 삭제)
+					$("#freeGoodsPromotionForm input[name=extmallYn]").addClass("formControl");
+					$("#freeGoodsPromotionForm .disabledPoint").prop("disabled", true);
+					$("#freeGoodsPromotionForm input").prop("disabled", true);
+					$("#freeGoodsPromotionForm button").hide();
+
+					// 진행 상태일 경우 노출 버튼 (저장 버튼은 중지시 수정 불가처리하기로하여 주석처리. 기획서대로 변경일 경우 주석 제거 및 if 제거)
+					if(freegift.freegiftStat == "G232_11") {	// 진행 상태일 경우
+						// $("#freeGoodsPromotionForm #btnFreegoodsPromotionSave").show();	// 저장
+						$("#freeGoodsPromotionForm #btnPromotionStop").show();				// 중지
+					}
+
+					// 목록 버튼
+					$("#freeGoodsPromotionForm #btnSearchList").show();
+
+					gridOptionsFreeGoods1List.columnApi.getColumn("usePoint").colDef.editable = false;
+					gridOptionsFreeGoods1List.columnApi.getColumn("itemQty").colDef.editable = false;
+					gridOptionsFreeGoods1List.columnApi.getColumn("limitQty").colDef.editable = false;
+					gridOptionsFreeGoods2List.columnApi.getColumn("usePoint").colDef.editable = false;
+					gridOptionsFreeGoods2List.columnApi.getColumn("itemQty").colDef.editable = false;
+					gridOptionsFreeGoods2List.columnApi.getColumn("limitQty").colDef.editable = false;
+				//}
 			}
 
 			gridOptionsFGExtmallList.api.setRowData(freegift.extmallList);
@@ -563,9 +615,13 @@
 
 			// 기간 검색 default 조건 (오늘부터 1주일)
 			let date = new Date();
-			$("#freeGoodsPromotionForm #freegiftStdt").val(date.format("YYYY-MM-DD"));	// 오늘 날짜
-			date.setDate(date.getDate() + 7);											// 등록일 + 7일
-			$("#freeGoodsPromotionForm #freegiftEddt").val(date.format("YYYY-MM-DD"));	// 1주일 후 날짜
+			$("#freeGoodsPromotionForm #freegiftStDate").val(date.format("YYYY-MM-DD"));	// 오늘 날짜
+			date.setDate(date.getDate() + 7);												// 등록일 + 7일
+			$("#freeGoodsPromotionForm #freegiftStDate").val(date.format("YYYY-MM-DD"));	// 1주일 후 날짜
+
+			$('#freeGoodsPromotionForm #freegiftEdHH option:last').prop("selected", true);
+			$("#freeGoodsPromotionForm #freegiftEdMM option").hide();
+			$('#freeGoodsPromotionForm #freegiftEdMM option:first').show().prop("selected", true);
 		} else {
 			fnFreegiftSearch();
 		}
@@ -642,8 +698,10 @@
 	// 저장 후 콜백 함수
 	var fnFreeGoodsPromotionSaveFin = function(result) {
 		if("C" != [[${param.gbn}]]) {
+			fnFreeGoodsPromotionListSearch();
 			fnFreegiftSearch();
 		} else {
+			fnFreeGoodsPromotionListSearch();
 			uifnPopupClose('popupFreeGoodsPromotionRegi');
 		}
 	}
@@ -674,7 +732,14 @@
 
 		if (fromDate > toDate) {
 			mcxDialog.alert("시작일자는 종료일자 보다 늦을 수 없습니다.");
-			$('#freeGoodsPromotionForm input[name=freegiftStdt]').focus();
+			return false;
+		}
+
+		var sdt = new Date(fromDate);
+		var edt = new Date(toDate);
+		var dateDiff = Math.ceil((edt.getTime()-sdt.getTime())/(1000*3600*24));
+		if(dateDiff > 365) {
+			mcxDialog.alert("행사 기간은 1년을 초과 할 수 없습니다.");
 			return false;
 		}
 
@@ -776,26 +841,37 @@
 			mcxDialog.alert("사은품 조건2의 사은품은 최대 5개까지 등록가능합니다.");
 			return false;
 		}
-		if($("#freeGoodsPromotionForm #saleAmt2").val() != "" && $("#freeGoodsPromotionForm #saleAmt2").val() < 1) {
+		if($("#freeGoodsPromotionForm #saleAmt2").val() == "" || $("#freeGoodsPromotionForm #saleAmt2").val() < 1) {
 			if(freeGoods2Cnt > 0) {
 				mcxDialog.alert("사은품 조건2의 구매금액 조건을 설정해주세요.");
 				return false;
 			}
-		} else if (freeGoods2Cnt < 1) {
-			mcxDialog.alert("사은품 조건2의 사은품을 선택해주세요.");
-			return false;
+		} else {
+			if (freeGoods2Cnt < 1) {
+				mcxDialog.alert("사은품 조건2의 사은품을 선택해주세요.");
+				return false;
+			}
 		}
 
-
 		let selfYn = $("#freeGoodsPromotionForm input[name=selfYn]:checked").val();
 		if(!selfYn || selfYn == "") { selfYn = "N"; }
 
+		alert($("#freeGoodsPromotionForm select[name=freegiftEdHH]").val());
+
+		let freegiftStdt = $("#freeGoodsPromotionForm input[name=freegiftStDate]").val() + " " + $("#freeGoodsPromotionForm select[name=freegiftStHH]").val() + ":" + $("#freeGoodsPromotionForm select[name=freegiftStMM]").val() + ":00";
+		let freegiftEddt = $("#freeGoodsPromotionForm input[name=freegiftEdDate]").val();
+		if($("#freeGoodsPromotionForm select[name=freegiftEdHH]").val() == "24") {
+			freegiftEddt += " 23:59:59";
+		} else {
+			freegiftEddt += " " + $("#freeGoodsPromotionForm select[name=freegiftEdHH]").val() + ":" + $("#freeGoodsPromotionForm select[name=freegiftEdMM]").val() + ":00";
+		}
+
 		// var params =  $(formId).serialize();
 		var data = {  gbn : $("#freeGoodsPromotionForm input[name=gbn]").val()
 			        , freegiftSq : $("#freeGoodsPromotionForm input[name=freegiftSq]").val()
 			        , freegiftNm : $("#freeGoodsPromotionForm input[name=freegiftNm]").val()
-					, freegiftStdt : $("#freeGoodsPromotionForm input[name=freegiftStdt]").val().replace(/-/gi, "")
-					, freegiftEddt : $("#freeGoodsPromotionForm input[name=freegiftEddt]").val().replace(/-/gi, "")
+					, freegiftStdt : freegiftStdt
+					, freegiftEddt : freegiftEddt
 					, selfYn : selfYn
 					, extmallYn : $("#freeGoodsPromotionForm input[name=extmallYn]:checked").val()
 					, allYn : $("#freeGoodsPromotionForm input[name=allYn]:checked").val()
@@ -814,6 +890,16 @@
 		gagajf.ajaxJsonSubmit('/marketing/freeGoodsPromotion/save', jsonData, fnFreeGoodsPromotionSaveFin);
 	});
 
+	// 할인방식 변경
+	$("#freeGoodsPromotionForm #freegiftEdHH").bind('click change', function () {
+		if(this.value == 24) {
+			$("#freeGoodsPromotionForm #freegiftEdMM option").hide();
+			$('#freeGoodsPromotionForm #freegiftEdMM option:first').show().prop("selected", true);
+		} else {
+			$("#freeGoodsPromotionForm #freegiftEdMM option").show();
+		}
+	});
+
 	// 목록 버튼 클릭
 	$("#freeGoodsPromotionForm #btnSearchList").on("click", function() {
 		uifnPopupClose('popupFreeGoodsPromotionRegi');

+ 156 - 0
src/main/webapp/WEB-INF/views/marketing/PointGrantPopupForm.html

@@ -0,0 +1,156 @@
+<!DOCTYPE html>
+<html lang="ko"
+	  xmlns:th="http://www.thymeleaf.org">
+<!--
+ *******************************************************************************
+ * @source  : PointGrantPopupForm.html
+ * @desc    : 포인트부여 팝업 Page
+ *============================================================================
+ * STYLE24
+ * Copyright(C) 2021 TSIT, All rights reserved.
+ *============================================================================
+ * VER  DATE         AUTHOR      DESCRIPTION
+ * ===  ===========  ==========  =============================================
+ * 1.0  2021.01.27   jsshin     최초 작성
+ *******************************************************************************
+ -->
+<div class="modalPopup" data-width="640">
+	<div class="panelStyle">
+		<!-- TITLE -->
+		<div class="panelTitle">
+			<strong>포인트부여</strong>
+			<button type="button" class="close" onclick="uifnPopupClose('popupPointGrantForm')"><em class="fa fa-times"></em></button>
+		</div>
+		<!-- //TITLE -->
+		<!-- CONTENT -->
+		<div class="panelContent">
+			<div class="panelStyle">
+				<form id="pointGrantForm" name="pointGrantForm">
+					<input type="hidden" name="custNo">
+					<table class="frmStyle">
+						<colgroup>
+							<col style="width:10%"/>
+							<col style="width:40%"/>
+							<col style="width:10%"/>
+							<col style="width:40%"/>
+						</colgroup>
+						<tbody>
+						<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>
+							</td>
+						</tr>
+						<tr>
+							<th>포인트변경사유<em class="required" title="필수"></em></th>
+							<td>
+								<select name="occurGb" data-valid-name="포인트변경사유" required>
+									<option value="">선택하세요</option>
+									<option th:if="${occurGbList}" th:each="oneData, status : ${occurGbList}" th:value="${oneData.cd}" th:text="${oneData.cdNm}"></option>
+								</select>
+							</td>
+						</tr>
+						<tr>
+							<th>증감구분<em class="required" title="필수"></em></th>
+							<td>
+								<select name="signGb" data-valid-name="증감구분" required>
+									<option value="">선택하세요</option>
+									<option value="+">증가</option>
+									<option value="-">감소</option>
+								</select>
+							</td>
+						</tr>
+						<tr class="expire">
+							<th >만료일자</th>
+							<td>
+								<input type="text" name="expBeDt" th:value="${expBeDt}" class="schDate w100"/>
+							</td>
+						</tr>
+						<tr>
+							<th>적립포인트</th>
+							<td>
+								<input type="text" name="pntAmt" min="1" data-valid-name="적립포인트" data-valid-type="integer" maxlength="6" required/>
+							</td>
+						</tr>
+						<tr>
+							<th>상세사유</th>
+							<td colspan="3">
+								<textarea name="occurDtlDesc" class="textareaR4" style="resize: none;" data-valid-name="상세사유" required></textarea>
+							</td>
+						</tr>
+						</tbody>
+					</table>
+				</form>
+			</div>
+			<ul class="panelBar">
+				<li class="right">
+					<button type="button" id="btnSavePoint" class="btn btn-success btn-lg">포인트부여</button>
+				</li>
+			</ul>
+		</div>
+		<!-- //CONTENT -->
+	</div>
+</div>
+<script th:inline="javascript">
+	/*<![CDATA[*/
+	const elementCustNo = [[${elementCustNo}]];
+	const pntAssignAmt = [[${pntAssignAmt}]];
+
+	// 포인트 부여
+	$('#btnSavePoint').on('click', function () {
+		if(!gagajf.validation('#pointGrantForm'))
+			return;
+
+		gagajf.removeCommaAtNumberFormattedInput('#pointGrantForm');
+		let grantPoint = $("#pointGrantForm").serializeObject();
+
+		if (gagajf.isNull(grantPoint.custNo)) {
+			mcxDialog.alert("회원 아이디가 존재하지 않습니다. 관리자에게 문의바랍니다.");
+			return;
+		}
+
+		if (grantPoint.signGb === '+') {
+			if (pntAssignAmt === 0) {
+				mcxDialog.alert("지급가능한 포인트가 없습니다.");
+				return;
+			} else if (grantPoint.pntAmt > pntAssignAmt) {
+				mcxDialog.alert("지급가능한 포인트를 초과하였습니다.");
+				return;
+			}
+		}
+
+		// (+ + 1) -> 1, (- + 1) -> -1
+		let pntAmt = grantPoint.pntAmt * (grantPoint.signGb + 1)
+		grantPoint.pntAmt = pntAmt;
+
+		mcxDialog.confirm("포인트를 부여하시겠습니까?", {
+			cancelBtnText: "취소",
+			sureBtnText: "확인",
+			sureBtnClick: function() {
+				let jsonData = JSON.stringify(grantPoint);
+				//console.log('jsonData', jsonData);
+				gagajf.ajaxJsonSubmit('/marketing/point/save',jsonData , fnSavePointCallBack);
+			}
+		});
+	});
+
+	var fnSavePointCallBack = function () {
+		uifnPopupClose('popupPointGrantForm');
+		fnSearchPoint();
+	};
+
+	var fnInitDataSet = function () {
+		let custNo = $(elementCustNo).val();
+		if(!gagajf.isNull(custNo)) {
+			$('#pointGrantForm input[name=custNo]').val(custNo);
+		}
+	};
+
+	$(document).ready(function() {
+		fnInitDataSet();
+	});
+	/*]]>*/
+</script>
+</html>

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

@@ -313,7 +313,7 @@ var columnExchangeReqList = [
 					strVal += '<select class="ordCanChgQty ' + params.data.ordDtlNo + '" name="chgQty" ordDtlNo="'+params.data.ordDtlNo+'" onchange="fnChangeQty(this)">';
 					
 					for (i=0 ; i<=ordCanChgQty ; i++) {
-						if (i == params.data.ordCanChgQty) {
+						if (i == params.data.chgQty) {
 							strVal += "	<option value='"+i+"' selected>"+i+"</option>";
 						} else {
 							strVal += "	<option value='"+i+"'>"+i+"</option>";
@@ -543,8 +543,8 @@ var fnChangeChgReason = function(reasonCd){
 		$("#imputeReason").text("회사");
 	}
 
-	$('#cancelRequestFrm input[name=chgReason]').val(arrReasonCd[0]);
-	$('#cancelRequestFrm input[name=chgReasonDesc]').val(arrReasonCd[1]);
+	$('#exchangeRequestFrm input[name=chgReason]').val(arrReasonCd[0]);
+	$('#exchangeRequestFrm input[name=chgReasonDesc]').val(arrReasonCd[1]);
 	
 	// 추가배송비 설정
 	fnChangeQty();
@@ -552,14 +552,13 @@ var fnChangeChgReason = function(reasonCd){
 
 // 교환요청
 var fnExchange = function () {
-	console.log('a');
 	var qty		= false;
 	var opt		= false;
 	var wdGb	= $('#wdGb:checked').val();
 
 	// 1. 교환수량 체크
 	$.each(cancelRequestTargetList, function(idx, item) {
-		if (item.ordCanChgQty > 0) {
+		if (item.chgQty > 0) {
 			qty = true;
 			
 			if (!gagajf.isNull(item.ordChgOpt)) {
@@ -679,6 +678,7 @@ var fnExchange = function () {
 		,"chgerDtlAddr"		: chgerDtlAddr
 		,"chgerPhnno"		: chgerPhnno
 		,"chgerTelno"		: chgerTelno
+		,"chgerRtnMemo"		: $("#exchangeRequestFrm textarea[name=chgerRtnMemo]").val()
 		,"recipNm"			: recipNm
 		,"recipEmail"		: recipEmail
 		,"recipZipcode"		: recipZipcode
@@ -686,6 +686,7 @@ var fnExchange = function () {
 		,"recipDtlAddr"		: recipDtlAddr
 		,"recipPhnno"		: recipPhnno
 		,"recipTelno"		: recipTelno
+		,"delvMemo"			: $("#exchangeRequestFrm textarea[name=delvMemo]").val()
 	}
 
 	// 주문번호, 교환사유, 교환메모, (취소, 반품, 교환 신청 정보 목록)
@@ -699,9 +700,9 @@ var fnExchange = function () {
 				'/orderChange/exchangeRequest/'
 				, jsonData
 				, function() {
-					//uifnPopupClose('popupOrderDetail');
-					//fnReOpenOrderDetailPopup();
-					//uifnPopupClose('popupReturnRequestForm');
+					uifnPopupClose('popupOrderDetail');
+					fnReOpenOrderDetailPopup();
+					uifnPopupClose('popupExchangeRequestForm');
 				}
 			);
 		}
@@ -802,7 +803,7 @@ var fnChangeOption = function(param) {
 
 // 교환수량 변경 이벤트
 var fnChangeQty = function(param) {
-	var ordCanChgQty = $(param).val();
+	var chgQty = $(param).val();
 	var ordDtlNo = $(param).attr('ordDtlNo');
 	var exchangeRequestTargetList = [];
 
@@ -813,12 +814,12 @@ var fnChangeQty = function(param) {
 				return false;
 			}
 			
-			item.ordCanChgQty = ordCanChgQty;
+			item.chgQty = chgQty;
 			
-			if (ordCanChgQty > 0) {
+			if (chgQty > 0) {
 				exchangeRequestTargetList.push(item);
 			}
-		} else if (item.ordCanChgQty > 0) {
+		} else if (item.chgQty > 0) {
 			exchangeRequestTargetList.push(item);
 		}
 	});

+ 2 - 14
src/main/webapp/ux/js/admin.popup.js

@@ -429,26 +429,14 @@ var cfnOpenEmailPopup = function(param, division) {
  * @type   : function
  * @access : public
  * @desc   : 쿠폰발급팝업
- * @since  : 2020/02/18
- * @author : 이명철
+ * @author : xyzp1539
+ * @since  : 2021-01-21
  */
 var cfnCpnPubForCustPopup = function(){
 	var actionUrl = '/marketing/coupon/cpnPubForCust/popup/form';
 	cfnOpenModalPopup(actionUrl, 'CpnPubForCustPopup');
 }
 
-/**
- * @type   : function
- * @access : public
- * @desc   : 포인트부여팝업
- * @since  : 2020/02/18
- * @author : 이명철
- */
-var cfnGrantPointPopup = function(){
-	var actionUrl = '/customer/point/grantPoint/popup/form';
-	cfnOpenModalPopup(actionUrl, 'GrantPointPopup');
-}
-
 /**
  * @type   : function
  * @access : public