swkim 4 лет назад
Родитель
Сommit
a98c221f85

+ 13 - 0
src/main/java/com/style24/admin/biz/dao/TsaStatisticsDao.java

@@ -6,6 +6,7 @@ import com.gagaframework.web.parameter.GagaMap;
 import com.style24.core.support.annotation.ShopDs;
 import com.style24.persistence.domain.Card;
 import com.style24.persistence.domain.Statistics;
+import jdk.internal.dynalink.beans.StaticClass;
 
 /**
  * 통계 Dao
@@ -179,4 +180,16 @@ public interface TsaStatisticsDao {
 
 	Collection<Statistics> getCustomerAgeOrderList(Statistics statistics);
 
+	Collection<Statistics> getCustomerRankingList(Statistics statistics);
+
+	Collection<Statistics> getCustomerUnloginList();
+
+	Collection<Statistics> getCustomerUnloginInfoList();
+
+	Collection<Statistics> getCustomerMarketingList();
+
+	Collection<Statistics> getCustomerDormRemainList();
+
+	Collection<Statistics> getCustomerDormRemainInfoList();
+
 }

+ 24 - 0
src/main/java/com/style24/admin/biz/service/TsaStatisticsService.java

@@ -309,4 +309,28 @@ public class TsaStatisticsService {
 	public Collection<Statistics> getCustomerAgeOrderList(Statistics statistics) {
 		return statisticsDao.getCustomerAgeOrderList(statistics);
 	}
+
+	public Collection<Statistics> getCustomerRankingList(Statistics statistics) {
+		return statisticsDao.getCustomerRankingList(statistics);
+	}
+
+	public Collection<Statistics> getCustomerUnloginList() {
+		return statisticsDao.getCustomerUnloginList();
+	}
+
+	public Collection<Statistics> getCustomerUnloginInfoList() {
+		return statisticsDao.getCustomerUnloginInfoList();
+	}
+
+	public Collection<Statistics> getCustomerMarketingList() {
+		return statisticsDao.getCustomerMarketingList();
+	}
+
+	public Collection<Statistics> getCustomerDormRemainList() {
+		return statisticsDao.getCustomerDormRemainList();
+	}
+
+	public Collection<Statistics> getCustomerDormRemainInfoList() {
+		return statisticsDao.getCustomerDormRemainInfoList();
+	}
 }

+ 58 - 0
src/main/java/com/style24/admin/biz/web/TsaStatisticsController.java

@@ -969,4 +969,62 @@ public class TsaStatisticsController extends TsaBaseController {
 
 		return statisticsService.getCustomerAgeOrderList(statistics);
 	}
+
+	/**
+	 * 구매자랭킹 화면
+	 * @return
+	 * @author swkim
+	 * @since 2021. 9. 28
+	 */
+	@GetMapping("/customer/ranking/form")
+	public ModelAndView customerRankingForm() {
+		ModelAndView mav = new ModelAndView();
+
+		mav.setViewName("statistics/CustomerRankingForm");
+
+		return mav;
+	}
+
+	/**
+	 * 구매자랭킹 조회
+	 * author: swkim
+	 * return: Collection<Statistics>
+	 * since: 2021. 9. 28.
+	 */
+	@PostMapping("/customer/ranking/list")
+	@ResponseBody
+	public Collection<Statistics> getCustomerRankingList(@RequestBody Statistics statistics) {
+
+		if (!StringUtils.isBlank(statistics.getBrandCdList())) {
+			statistics.setMultiBrandCd(statistics.getBrandCdList().split(","));
+		}
+
+		if (!StringUtils.isBlank(statistics.getItemkindCdList())) {
+			statistics.setMultiItemkindCd(statistics.getItemkindCdList().split(","));
+		}
+
+		return statisticsService.getCustomerRankingList(statistics);
+	}
+
+	/**
+	 * 회원활동현황 화면
+	 * @return
+	 * @author swkim
+	 * @since 2021. 9. 28
+	 */
+	@GetMapping("/customer/active/form")
+	public ModelAndView customerActiveForm() {
+		ModelAndView mav = new ModelAndView();
+
+		//미로그인회원형황
+		mav.addObject("unloginList", statisticsService.getCustomerUnloginList());
+		//마케팅수신동의현황
+		mav.addObject("marketingList", statisticsService.getCustomerMarketingList());
+		//휴면전환 잔여일별 회원현황
+		mav.addObject("dormRemainList", statisticsService.getCustomerDormRemainList());
+
+		mav.setViewName("statistics/CustomerActiveForm");
+
+		return mav;
+	}
 }

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

@@ -264,4 +264,6 @@ public class Statistics extends TscBaseDomain {
 	@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
 	private String[] multiGradeGb;
 
+	private String custId;
+	private int custPoint;
 }

+ 550 - 0
src/main/java/com/style24/persistence/mybatis/shop/TsaStatistics.xml

@@ -2085,4 +2085,554 @@
 		ORDER BY A.AGE, A.SEX_GB
 	</select>
 
+	<!-- 구매자랭킹 -->
+	<select id="getCustomerRankingList" parameterType="Statistics" resultType="Statistics">
+		/* TsaStatistics.getCustomerRankingList */
+		WITH TAB AS (
+			SELECT *
+			FROM (
+			SELECT A.ORD_NO
+				, B.ORD_DTL_NO
+				, B.ORD_QTY
+				, B.CNCL_RTN_QTY
+				, B.ORD_AMT
+				, B.CNCL_RTN_AMT
+				, B.CPN1_DC_AMT
+				, A.PAY_DT
+				, A.FRONT_GB
+				, C.ITEMKIND_CD
+				, C.BRAND_CD
+				, E.CUST_NO
+				, E.CUST_GRADE
+				, RANK() OVER (PARTITION BY B.ORD_DTL_NO ORDER BY B.ORD_DTL_HST_SQ) AS RNK
+			FROM TB_ORDER A,
+				TB_ORDER_DETAIL_HST B,
+				TB_GOODS C,
+				TB_CUSTOMER E
+			WHERE A.ORD_NO = B.ORD_NO
+				AND B.GOODS_CD = C.GOODS_CD
+				AND A.CUST_NO = E.CUST_NO
+				AND A.PAY_DT >= STR_TO_DATE(#{startDt},'%Y-%m-%d')                         -- 시작일변수
+				AND A.PAY_DT <![CDATA[<]]> DATE_ADD(STR_TO_DATE(#{endDt},'%Y-%m-%d'), INTERVAL 1 DAY) -- 종료일변수
+				AND E.CUST_NO > 0
+				AND A.MALL_GB = 'G011_10'
+				AND B.ORD_EXCH_GB = 'O'
+				AND B.ORD_DTL_STAT = 'G013_20' -- 결제완료
+		<if test="multiFrontGb != null">
+			/* 디바이스 */
+			<foreach collection="multiFrontGb" item="item" index="index"  open="AND A.FRONT_GB IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+		<if test="multiSexGb != null">
+			/* 성별구분 */
+			<foreach collection="multiSexGb" item="item" index="index"  open="AND FN_DEC_AES(E.SEX_GB) IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+		<if test="multiAgeGb != null">
+			/* 연령구분 */
+			<foreach collection="multiAgeGb" item="item" index="index"  open="AND CASE WHEN FN_DEC_AES(E.BIRTH_YMD) = '' OR FN_DEC_AES(E.BIRTH_YMD) IS NULL THEN 'X'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(E.BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 10 AND 19 THEN '10'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(E.BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 20 AND 29 THEN '20'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(E.BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 30 AND 39 THEN '30'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(E.BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 40 AND 49 THEN '40'
+				ELSE 'X' END IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+		<if test="multiBrandCd != null">
+			/* 브랜드 */
+			<foreach collection="multiBrandCd" item="item" index="index"  open="AND BRAND_CD IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+		<if test="multiItemkindCd != null">
+			/* 품목 */
+			<foreach collection="multiItemkindCd" item="item" index="index"  open="AND ITEMKIND_CD IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+			) A
+			WHERE RNK = 1
+		)
+		-- 판매수
+		, TAB_SELL_QTY AS (
+			SELECT
+				SUM(ORD_QTY) AS VAL
+				, '1' AS GBN
+				, CUST_NO
+			FROM TAB
+			GROUP BY CUST_NO
+		)
+		-- 매출
+		, TAB_ORD AS (
+			SELECT
+				SUM(ORD_AMT + CPN1_DC_AMT + (SELECT SUM(OPT_ADD_PRICE * ITEM_QTY) FROM TB_ORDER_DETAIL_ITEM X WHERE X.ORD_DTL_NO = A.ORD_DTL_NO)) AS VAL
+				, '2' AS GBN
+				, CUST_NO
+			FROM TAB A
+			GROUP BY CUST_NO
+		)
+		-- 취소갯수
+		, TAB_CNCL_QTY AS (
+			SELECT SUM(CHG_QTY) AS VAL
+				, '3' AS GBN
+				, C.CUST_NO
+			FROM TB_ORDER_CHANGE_DETAIL A, TB_ORDER_DETAIL B, TB_ORDER C, TB_GOODS E, TB_CUSTOMER G
+			WHERE A.ORD_DTL_NO = B.ORD_DTL_NO
+				AND B.ORD_NO = C.ORD_NO
+				AND B.GOODS_CD = E.GOODS_CD
+				AND C.CUST_NO = G.CUST_NO
+				AND CHG_STAT = 'G685_18' -- 결제후취소
+				AND COMPLETE_DT >= STR_TO_DATE(#{startDt},'%Y-%m-%d') -- 시작일변수
+				AND COMPLETE_DT <![CDATA[<]]> DATE_ADD(STR_TO_DATE(#{endDt},'%Y-%m-%d'), INTERVAL 1 DAY) -- 종료일변수
+				AND MALL_GB = 'G011_10'
+				AND G.CUST_NO > 0
+		<if test="multiFrontGb != null">
+			/* 디바이스 */
+			<foreach collection="multiFrontGb" item="item" index="index"  open="AND C.FRONT_GB IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+		<if test="multiSexGb != null">
+			/* 성별구분 */
+			<foreach collection="multiSexGb" item="item" index="index"  open="AND FN_DEC_AES(G.SEX_GB) IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+		<if test="multiAgeGb != null">
+			/* 연령구분 */
+			<foreach collection="multiAgeGb" item="item" index="index"  open="AND CASE WHEN FN_DEC_AES(G.BIRTH_YMD) = '' OR FN_DEC_AES(G.BIRTH_YMD) IS NULL THEN 'X'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(G.BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 10 AND 19 THEN '10'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(G.BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 20 AND 29 THEN '20'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(G.BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 30 AND 39 THEN '30'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(G.BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 40 AND 49 THEN '40'
+				ELSE 'X' END IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+		<if test="multiBrandCd != null">
+			/* 브랜드 */
+			<foreach collection="multiBrandCd" item="item" index="index"  open="AND BRAND_CD IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+		<if test="multiItemkindCd != null">
+			/* 품목 */
+			<foreach collection="multiItemkindCd" item="item" index="index"  open="AND ITEMKIND_CD IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+			GROUP BY C.CUST_NO
+		)
+		-- 반품갯수
+		, TAB_RTN_QTY AS (
+			SELECT SUM(CHG_QTY) AS VAL
+				, '4' AS GBN
+				, C.CUST_NO
+			FROM TB_ORDER_CHANGE_DETAIL A, TB_ORDER_DETAIL B, TB_ORDER C, TB_GOODS E, TB_CUSTOMER G
+			WHERE A.ORD_DTL_NO = B.ORD_DTL_NO
+				AND B.ORD_NO = C.ORD_NO
+				AND B.GOODS_CD = E.GOODS_CD
+				AND C.CUST_NO = G.CUST_NO
+				AND CHG_STAT = 'G685_60' -- 반품완료
+				AND COMPLETE_DT >= STR_TO_DATE(#{startDt},'%Y-%m-%d') -- 시작일변수
+				AND COMPLETE_DT <![CDATA[<]]> DATE_ADD(STR_TO_DATE(#{endDt},'%Y-%m-%d'), INTERVAL 1 DAY) -- 종료일변수
+				AND MALL_GB = 'G011_10'
+				AND G.CUST_NO > 0
+		<if test="multiFrontGb != null">
+			/* 디바이스 */
+			<foreach collection="multiFrontGb" item="item" index="index"  open="AND C.FRONT_GB IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+		<if test="multiSexGb != null">
+			/* 성별구분 */
+			<foreach collection="multiSexGb" item="item" index="index"  open="AND FN_DEC_AES(G.SEX_GB) IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+		<if test="multiAgeGb != null">
+			/* 연령구분 */
+			<foreach collection="multiAgeGb" item="item" index="index"  open="AND CASE WHEN FN_DEC_AES(G.BIRTH_YMD) = '' OR FN_DEC_AES(G.BIRTH_YMD) IS NULL THEN 'X'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(G.BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 10 AND 19 THEN '10'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(G.BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 20 AND 29 THEN '20'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(G.BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 30 AND 39 THEN '30'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(G.BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 40 AND 49 THEN '40'
+				ELSE 'X' END IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+		<if test="multiBrandCd != null">
+			/* 브랜드 */
+			<foreach collection="multiBrandCd" item="item" index="index"  open="AND BRAND_CD IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+		<if test="multiItemkindCd != null">
+			/* 품목 */
+			<foreach collection="multiItemkindCd" item="item" index="index"  open="AND ITEMKIND_CD IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+			GROUP BY C.CUST_NO
+		)
+		-- 취소액
+		, TAB_CNCL_AMT AS (
+			SELECT SUM((C.CURR_PRICE + (SELECT SUM(OPT_ADD_PRICE * ITEM_QTY) FROM TB_ORDER_DETAIL_ITEM X WHERE X.ORD_DTL_NO = C.ORD_DTL_NO)) * B.CHG_QTY) AS VAL
+				, '5' AS GBN
+				, D.CUST_NO
+			FROM TB_ORDER_CHANGE_DETAIL B, TB_ORDER_DETAIL C, TB_ORDER D, TB_GOODS E, TB_CUSTOMER G
+			WHERE B.ORD_DTL_NO = C.ORD_DTL_NO
+				AND C.ORD_NO = D.ORD_NO
+				AND C.GOODS_CD = E.GOODS_CD
+				AND D.CUST_NO = G.CUST_NO
+				AND CHG_STAT = 'G685_18' -- 결제후취소
+				AND B.COMPLETE_DT >= STR_TO_DATE(#{startDt},'%Y-%m-%d') -- 시작일변수
+				AND B.COMPLETE_DT <![CDATA[<]]> DATE_ADD(STR_TO_DATE(#{endDt},'%Y-%m-%d'), INTERVAL 1 DAY) -- 종료일변수
+				AND MALL_GB = 'G011_10'
+				AND G.CUST_NO > 0
+		<if test="multiFrontGb != null">
+			/* 디바이스 */
+			<foreach collection="multiFrontGb" item="item" index="index"  open="AND D.FRONT_GB IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+		<if test="multiSexGb != null">
+			/* 성별구분 */
+			<foreach collection="multiSexGb" item="item" index="index"  open="AND FN_DEC_AES(G.SEX_GB) IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+		<if test="multiAgeGb != null">
+			/* 연령구분 */
+			<foreach collection="multiAgeGb" item="item" index="index"  open="AND CASE WHEN FN_DEC_AES(G.BIRTH_YMD) = '' OR FN_DEC_AES(G.BIRTH_YMD) IS NULL THEN 'X'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(G.BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 10 AND 19 THEN '10'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(G.BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 20 AND 29 THEN '20'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(G.BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 30 AND 39 THEN '30'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(G.BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 40 AND 49 THEN '40'
+				ELSE 'X' END IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+		<if test="multiBrandCd != null">
+			/* 브랜드 */
+			<foreach collection="multiBrandCd" item="item" index="index"  open="AND BRAND_CD IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+		<if test="multiItemkindCd != null">
+			/* 품목 */
+			<foreach collection="multiItemkindCd" item="item" index="index"  open="AND ITEMKIND_CD IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+			GROUP BY D.CUST_NO
+		)
+		-- 반품액
+		, TAB_RTN_AMT AS (
+			SELECT SUM((C.CURR_PRICE + (SELECT SUM(OPT_ADD_PRICE * ITEM_QTY) FROM TB_ORDER_DETAIL_ITEM X WHERE X.ORD_DTL_NO = C.ORD_DTL_NO)) * B.CHG_QTY) AS VAL
+				, '6' AS GBN
+				, D.CUST_NO
+			FROM TB_ORDER_CHANGE_DETAIL B, TB_ORDER_DETAIL C, TB_ORDER D, TB_GOODS E, TB_CUSTOMER G
+			WHERE B.ORD_DTL_NO = C.ORD_DTL_NO
+				AND C.ORD_NO = D.ORD_NO
+				AND C.GOODS_CD = E.GOODS_CD
+				AND D.CUST_NO = G.CUST_NO
+				AND CHG_STAT = 'G685_60' -- 반품완료
+				AND B.COMPLETE_DT >= STR_TO_DATE(#{startDt},'%Y-%m-%d') -- 시작일변수
+				AND B.COMPLETE_DT <![CDATA[<]]> DATE_ADD(STR_TO_DATE(#{endDt},'%Y-%m-%d'), INTERVAL 1 DAY) -- 종료일변수
+				AND MALL_GB = 'G011_10'
+				AND G.CUST_NO > 0
+		<if test="multiFrontGb != null">
+			/* 디바이스 */
+			<foreach collection="multiFrontGb" item="item" index="index"  open="AND D.FRONT_GB IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+		<if test="multiSexGb != null">
+			/* 성별구분 */
+			<foreach collection="multiSexGb" item="item" index="index"  open="AND FN_DEC_AES(G.SEX_GB) IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+		<if test="multiAgeGb != null">
+			/* 연령구분 */
+			<foreach collection="multiAgeGb" item="item" index="index"  open="AND CASE WHEN FN_DEC_AES(G.BIRTH_YMD) = '' OR FN_DEC_AES(G.BIRTH_YMD) IS NULL THEN 'X'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(G.BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 10 AND 19 THEN '10'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(G.BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 20 AND 29 THEN '20'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(G.BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 30 AND 39 THEN '30'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(G.BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 40 AND 49 THEN '40'
+				ELSE 'X' END IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+		<if test="multiBrandCd != null">
+			/* 브랜드 */
+			<foreach collection="multiBrandCd" item="item" index="index"  open="AND BRAND_CD IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+		<if test="multiItemkindCd != null">
+			/* 품목 */
+			<foreach collection="multiItemkindCd" item="item" index="index"  open="AND ITEMKIND_CD IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+			GROUP BY D.CUST_NO
+		)
+		-- 주문수
+		, TAB_ORD_CNT AS (
+			SELECT
+				SUM(VAL) AS VAL
+				, '7' AS GBN
+				, CUST_NO
+			FROM (
+				SELECT
+					1 AS VAL
+					, ORD_NO
+					, CUST_NO
+				FROM TAB
+				GROUP BY ORD_NO, CUST_NO
+			) A
+			GROUP BY CUST_NO
+		)
+		SELECT
+			CONCAT(SUBSTRING(CUST_ID, 1, 3), '****', '(', SUBSTRING(FN_DEC_AES(CUST_NM), 1, 1), '**', ')') AS CUST_ID -- 아이디
+			, CASE WHEN FN_DEC_AES(BIRTH_YMD) = '' OR FN_DEC_AES(BIRTH_YMD) IS NULL THEN 'X'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 10 AND 19 THEN '10'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 20 AND 29 THEN '20'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 30 AND 39 THEN '30'
+				WHEN (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(CONCAT(SUBSTRING(FN_DEC_AES(BIRTH_YMD), 1, 4), '0101'), '%Y') + 1) BETWEEN 40 AND 49 THEN '40'
+			ELSE 'X' END AS AGE
+			, FN_GET_CODE_NM('G007', FN_DEC_AES(SEX_GB)) AS SEX_GB
+			, FN_GET_CODE_NM('G110', CUST_GRADE) AS CUST_GRADE -- 등급
+			, SUM(ORD_AMT - CNCL_AMT - RTN_AMT) AS TOT_ORD_AMT -- 매출액
+			, SUM(ORD_CNT) AS ORD_CNT -- 주문수
+			, SUM(SELL_QTY - CNCL_QTY - RTN_QTY) AS SELL_QTY -- 판매수
+			, FLOOR(SUM(ORD_AMT) / SUM(ORD_CNT)) AS CUST_PRICE -- 객단가
+			, IFNULL((SELECT SUM(RM_PNT_AMT) FROM TB_CUST_POINT CP WHERE CP.CUST_NO = X.CUST_NO AND EXP_CMP_DT IS NULL), 0) AS CUST_POINT -- 회원포인트
+		FROM (
+			SELECT
+				CUST_NO
+				, SUM(CASE WHEN GBN = '1' THEN VAL ELSE 0 END) AS SELL_QTY -- 판매수
+				, SUM(CASE WHEN GBN = '2' THEN VAL ELSE 0 END) AS ORD_AMT -- 매출액(판매금액)
+				, SUM(CASE WHEN GBN = '3' THEN VAL ELSE 0 END) AS CNCL_QTY -- 취소수량
+				, SUM(CASE WHEN GBN = '4' THEN VAL ELSE 0 END) AS RTN_QTY -- 반품수량
+				, SUM(CASE WHEN GBN = '5' THEN VAL ELSE 0 END) AS CNCL_AMT -- 취소금액
+				, SUM(CASE WHEN GBN = '6' THEN VAL ELSE 0 END) AS RTN_AMT -- 반품금액
+				, SUM(CASE WHEN GBN = '7' THEN VAL ELSE 0 END) AS ORD_CNT -- 주문수
+			FROM (
+				SELECT * FROM TAB_SELL_QTY
+				UNION ALL
+				SELECT * FROM TAB_ORD
+				UNION ALL
+				SELECT * FROM TAB_CNCL_QTY
+				UNION ALL
+				SELECT * FROM TAB_RTN_QTY
+				UNION ALL
+				SELECT * FROM TAB_CNCL_AMT
+				UNION ALL
+				SELECT * FROM TAB_RTN_AMT
+				UNION ALL
+				SELECT * FROM TAB_ORD_CNT
+			) A
+			GROUP BY CUST_NO
+		) X, TB_CUSTOMER Y
+		WHERE X.CUST_NO = Y.CUST_NO
+		GROUP BY X.CUST_NO
+		ORDER BY TOT_ORD_AMT DESC
+		LIMIT 50
+	</select>
+
+	<!-- 미로그인현황 -->
+	<select id="getCustomerUnloginList" resultType="Statistics">
+		/* TsaStatistics.getCustomerUnloginList */
+		SELECT
+			X.*
+			, ROUND(CNT_5 / TOT_CNT * 100) AS PER_CNT_5
+			, ROUND(CNT_4 / TOT_CNT * 100) AS PER_CNT_4
+			, ROUND(CNT_3 / TOT_CNT * 100) AS PER_CNT_3
+			, ROUND(CNT_2 / TOT_CNT * 100) AS PER_CNT_2
+			, ROUND(CNT_1 / TOT_CNT * 100) AS PER_CNT_1
+		FROM (
+			SELECT
+				SUM(CASE WHEN GB = 5 THEN CNT ELSE 0 END) AS CNT_5
+				, SUM(CASE WHEN GB = 4 THEN CNT ELSE 0 END) AS CNT_4
+				, SUM(CASE WHEN GB = 3 THEN CNT ELSE 0 END) AS CNT_3
+				, SUM(CASE WHEN GB = 2 THEN CNT ELSE 0 END) AS CNT_2
+				, SUM(CASE WHEN GB = 1 THEN CNT ELSE 0 END) AS CNT_1
+				, SUM(CNT) AS TOT_CNT
+			FROM (
+				-- 1년
+				SELECT COUNT(1) AS CNT
+					, 5 AS GB -- 1년 ~
+				FROM TB_CUSTOMER
+				WHERE CUST_NO > 0
+					AND CUST_STAT = 'G104_10'
+					AND LOGIN_LDT &lt; DATE_FORMAT(DATE_ADD(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), INTERVAL -1 YEAR ), '%Y%m%d%H%i%s') -- now() 수정 : 조회시점의 시간까지만. ex) 2019년9월25일15시 조회 -> 20210925150000
+				-- 12개월
+				UNION ALL
+				SELECT COUNT(1) AS CNT
+					, 4 AS GB -- 9개월~12개월
+				FROM TB_CUSTOMER
+				WHERE CUST_NO > 0
+					AND CUST_STAT = 'G104_10'
+					AND LOGIN_LDT >= DATE_FORMAT(DATE_ADD(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), INTERVAL -1 YEAR ), '%Y%m%d%H%i%s')
+					AND LOGIN_LDT &lt; DATE_FORMAT(DATE_ADD(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), INTERVAL -9 MONTH ), '%Y%m%d%H%i%s')
+				-- 9개월
+				UNION ALL
+				SELECT COUNT(1) AS CNT
+					, 3 AS GB -- 6개월~9개월
+				FROM TB_CUSTOMER
+				WHERE CUST_NO > 0
+					AND CUST_STAT = 'G104_10'
+					AND LOGIN_LDT >= DATE_FORMAT(DATE_ADD(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), INTERVAL -9 MONTH ), '%Y%m%d%H%i%s')
+					AND LOGIN_LDT &lt; DATE_FORMAT(DATE_ADD(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), INTERVAL -6 MONTH ), '%Y%m%d%H%i%s')
+				-- 6개월
+				UNION ALL
+				SELECT COUNT(1) AS CNT
+					, 2 AS GB -- 3개월~6개월
+				FROM TB_CUSTOMER
+				WHERE CUST_NO > 0
+					AND CUST_STAT = 'G104_10'
+					AND LOGIN_LDT >= DATE_FORMAT(DATE_ADD(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), INTERVAL -6 MONTH ), '%Y%m%d%H%i%s')
+					AND LOGIN_LDT &lt; DATE_FORMAT(DATE_ADD(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), INTERVAL -3 MONTH ), '%Y%m%d%H%i%s')
+				-- 3개월
+				UNION ALL
+				SELECT COUNT(1) AS CNT
+					, 1 AS GB -- ~3개월
+				FROM TB_CUSTOMER
+				WHERE CUST_NO > 0
+					AND CUST_STAT = 'G104_10'
+					AND LOGIN_LDT >= DATE_FORMAT(DATE_ADD(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), INTERVAL -3 MONTH ), '%Y%m%d%H%i%s')
+					AND LOGIN_LDT &lt; DATE_FORMAT(NOW(), '%Y%m%d%H%i%s')
+			) Z
+		) X
+	</select>
+
+	<!-- 미로그인현황 회원리스트 -->
+	<select id="getCustomerUnloginInfoList" resultType="Statistics">
+		/* TsaStatistics.getCustomerUnloginInfoList */
+		SELECT
+			CUST_ID
+			, FN_DEC_AES(CUST_NM) AS CUST_NM
+			, TIMESTAMPDIFF(MONTH, LOGIN_LDT, NOW()) AS MONTHS
+			, FN_DEC_AES(CELL_PHNNO) AS CELL_PHNNO
+			, FN_DEC_AES(EMAIL) AS EMAIL
+			, SUBSTRING(FN_DEC_AES(BIRTH_YMD), 1, 6) AS BIRTH_YM
+		FROM TB_CUSTOMER
+		WHERE CUST_NO > 0
+			AND CUST_STAT = 'G104_10'
+			AND LOGIN_LDT &lt; DATE_FORMAT(STR_TO_DATE(DATE_FORMAT(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), '%Y%m%d%H'), '%Y%m%d%H'), '%Y%m%d%H%i%s') -- now() 수정 : 조회시점의 시간까지만. ex) 2019년9월25일15시 조회 -> 20210925150000
+	</select>
+
+	<!-- 마케팅수신동의현황 -->
+	<select id="getCustomerMarketingList" resultType="Statistics">
+		/* TsaStatistics.getCustomerMarketingList */
+		SELECT
+			X.*
+			 , ROUND(CNT_4 / TOT_CNT * 100) AS PER_CNT_4
+			 , ROUND(CNT_3 / TOT_CNT * 100) AS PER_CNT_3
+			 , ROUND(CNT_2 / TOT_CNT * 100) AS PER_CNT_2
+			 , ROUND(CNT_1 / TOT_CNT * 100) AS PER_CNT_1
+		FROM (
+			 SELECT SUM(CASE WHEN GB = 4 THEN CNT ELSE 0 END) AS CNT_4
+				  , SUM(CASE WHEN GB = 3 THEN CNT ELSE 0 END) AS CNT_3
+				  , SUM(CASE WHEN GB = 2 THEN CNT ELSE 0 END) AS CNT_2
+				  , SUM(CASE WHEN GB = 1 THEN CNT ELSE 0 END) AS CNT_1
+				  , SUM(CNT)                                  AS TOT_CNT
+			 FROM (
+				  -- SMS
+				  SELECT COUNT(1) AS CNT
+					   , 4        AS GB
+				  FROM TB_CUSTOMER
+				  WHERE CUST_NO > 0
+					AND CUST_STAT = 'G104_10'
+					AND SMS_AGREE_YN = 'Y'
+					-- EMAIL
+				  UNION ALL
+				  SELECT COUNT(1) AS CNT
+					   , 3        AS GB
+				  FROM TB_CUSTOMER
+				  WHERE CUST_NO > 0
+					AND CUST_STAT = 'G104_10'
+					AND EMAIL_AGREE_YN = 'Y'
+					-- 푸쉬
+				  UNION ALL
+				  SELECT COUNT(1) AS CNT
+					   , 2        AS GB
+				  FROM TB_CUSTOMER
+				  WHERE CUST_NO > 0
+					AND CUST_STAT = 'G104_10'
+					AND APP_AGREE_YN = 'Y'
+					-- 미동의
+				  UNION ALL
+				  SELECT COUNT(1) AS CNT
+					   , 1        AS GB
+				  FROM TB_CUSTOMER
+				  WHERE CUST_NO > 0
+					AND CUST_STAT = 'G104_10'
+					AND SMS_AGREE_YN = 'N'
+					AND EMAIL_AGREE_YN = 'N'
+					AND APP_AGREE_YN = 'N'
+			  ) Z
+		 ) X
+	</select>
+
+	<!-- 휴면전환 잔여일별현황 -->
+	<select id="getCustomerDormRemainList" resultType="Statistics">
+		/* TsaStatistics.getCustomerDormRemainList */
+		SELECT
+			SUM(CASE WHEN GB = 4 THEN CNT ELSE 0 END) AS CNT_4 -- 12개월
+			, SUM(CASE WHEN GB = 3 THEN CNT ELSE 0 END) AS CNT_3 -- 9개월
+			, SUM(CASE WHEN GB = 2 THEN CNT ELSE 0 END) AS CNT_2 -- 6개월
+			, SUM(CASE WHEN GB = 1 THEN CNT ELSE 0 END) AS CNT_1 -- 9개월
+		FROM (
+			-- 12개월
+			SELECT COUNT(1) AS CNT
+				, 4 AS GB -- 12개월
+			FROM TB_CUSTOMER
+			WHERE CUST_NO > 0
+				AND CUST_STAT = 'G104_10'
+				AND LOGIN_LDT &lt; DATE_FORMAT(DATE_ADD(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), INTERVAL -1 DAY ), '%Y%m%d%H%i%s') -- now() 수정 : 조회시점의 시간까지만. ex) 2019년9월25일15시 조회 -> 20210925150000
+			-- 9개월
+			UNION ALL
+			SELECT COUNT(1) AS CNT
+				, 3 AS GB -- 9개월
+			FROM TB_CUSTOMER
+			WHERE CUST_NO > 0
+				AND CUST_STAT = 'G104_10'
+				AND LOGIN_LDT >= DATE_FORMAT(DATE_ADD(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), INTERVAL -3 MONTH ), '%Y%m%d%H%i%s')
+				AND LOGIN_LDT &lt; DATE_FORMAT(DATE_ADD(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), INTERVAL -1 DAY ), '%Y%m%d%H%i%s')
+			-- 6개월
+			UNION ALL
+			SELECT COUNT(1) AS CNT
+				, 2 AS GB -- 6개월
+			FROM TB_CUSTOMER
+			WHERE CUST_NO > 0
+				AND CUST_STAT = 'G104_10'
+				AND LOGIN_LDT >= DATE_FORMAT(DATE_ADD(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), INTERVAL -6 MONTH ), '%Y%m%d%H%i%s')
+				AND LOGIN_LDT &lt; DATE_FORMAT(DATE_ADD(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), INTERVAL -3 MONTH ), '%Y%m%d%H%i%s')
+			-- 3개월
+			UNION ALL
+			SELECT COUNT(1) AS CNT
+				, 1 AS GB -- ~3개월
+			FROM TB_CUSTOMER
+			WHERE CUST_NO > 0
+				AND CUST_STAT = 'G104_10'
+				AND LOGIN_LDT >= DATE_FORMAT(DATE_ADD(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), INTERVAL -9 MONTH ), '%Y%m%d%H%i%s')
+				AND LOGIN_LDT &lt; DATE_FORMAT(DATE_ADD(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), INTERVAL -6 MONTH ), '%Y%m%d%H%i%s')
+		) Z
+	</select>
+
+	<!-- 휴면전환 잔여일별현황 회원리스트 -->
+	<select id="getCustomerDormRemainInfoList" resultType="Statistics">
+	/* TsaStatistics.getCustomerDormRemainInfoList */
+		SELECT
+			*
+		FROM (
+			-- 12개월
+			SELECT '12개월' AS GB -- 12개월
+				, CUST_ID
+				, FN_DEC_AES(CUST_NM) AS CUST_NM
+				, FN_DEC_AES(CELL_PHNNO) AS CELL_PHNNO
+				, FN_DEC_AES(EMAIL) AS EMAIL
+				, SUBSTRING(FN_DEC_AES(BIRTH_YMD), 1, 6) AS BIRTH_YM
+			FROM TB_CUSTOMER
+			WHERE CUST_NO > 0
+				AND CUST_STAT = 'G104_10'
+				AND LOGIN_LDT > DATE_FORMAT(DATE_ADD(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), INTERVAL -1 DAY ), '%Y%m%d%H%i%s') -- now() 수정 : 조회시점의 시간까지만. ex) 2019년9월25일15시 조회 -> 20210925150000
+			-- 9개월
+			UNION ALL
+			SELECT '9개월' AS GB -- 9개월
+				, CUST_ID
+				, FN_DEC_AES(CUST_NM) AS CUST_NM
+				, FN_DEC_AES(CELL_PHNNO) AS CELL_PHNNO
+				, FN_DEC_AES(EMAIL) AS EMAIL
+				, SUBSTRING(FN_DEC_AES(BIRTH_YMD), 1, 6) AS BIRTH_YM
+			FROM TB_CUSTOMER
+			WHERE CUST_NO > 0
+				AND CUST_STAT = 'G104_10'
+				AND LOGIN_LDT >= DATE_FORMAT(DATE_ADD(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), INTERVAL -3 MONTH ), '%Y%m%d%H%i%s')
+				AND LOGIN_LDT &lt; DATE_FORMAT(DATE_ADD(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), INTERVAL -1 DAY ), '%Y%m%d%H%i%s')
+			-- 6개월
+			UNION ALL
+			SELECT '6개월' AS GB -- 6개월
+				, CUST_ID
+				, FN_DEC_AES(CUST_NM) AS CUST_NM
+				, FN_DEC_AES(CELL_PHNNO) AS CELL_PHNNO
+				, FN_DEC_AES(EMAIL) AS EMAIL
+				, SUBSTRING(FN_DEC_AES(BIRTH_YMD), 1, 6) AS BIRTH_YM
+			FROM TB_CUSTOMER
+			WHERE CUST_NO > 0
+				AND CUST_STAT = 'G104_10'
+				AND LOGIN_LDT >= DATE_FORMAT(DATE_ADD(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), INTERVAL -6 MONTH ), '%Y%m%d%H%i%s')
+				AND LOGIN_LDT &lt; DATE_FORMAT(DATE_ADD(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), INTERVAL -3 MONTH ), '%Y%m%d%H%i%s')
+			-- 3개월
+			UNION ALL
+			SELECT '3개월' AS GB -- ~3개월
+				, CUST_ID
+				, FN_DEC_AES(CUST_NM) AS CUST_NM
+				, FN_DEC_AES(CELL_PHNNO) AS CELL_PHNNO
+				, FN_DEC_AES(EMAIL) AS EMAIL
+			, SUBSTRING(FN_DEC_AES(BIRTH_YMD), 1, 6) AS BIRTH_YM
+			FROM TB_CUSTOMER
+			WHERE CUST_NO > 0
+				AND CUST_STAT = 'G104_10'
+				AND LOGIN_LDT >= DATE_FORMAT(DATE_ADD(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), INTERVAL -9 MONTH ), '%Y%m%d%H%i%s')
+				AND LOGIN_LDT &lt; DATE_FORMAT(DATE_ADD(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), INTERVAL -6 MONTH ), '%Y%m%d%H%i%s')
+		) Z
+	</select>
 </mapper>

+ 38 - 0
src/main/webapp/WEB-INF/views/statistics/CustomerActiveForm.html

@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html lang="ko"
+	xmlns:th="http://www.thymeleaf.org">
+<!--
+ *******************************************************************************
+ * @source  : CustomerActiveForm.html
+ * @desc    : 회원활동현황 Page
+ *============================================================================
+ * STYLE24
+ * Copyright(C) 2020 TSIT, All rights reserved.
+ *============================================================================
+ * VER  DATE         AUTHOR      DESCRIPTION
+ * ===  ===========  ==========  =============================================
+ * 1.0  2021.09.28   swkim       최초 작성
+ *******************************************************************************
+ -->
+	<div id="main">
+		<!-- 메인타이틀 영역 -->
+		<div class="main-title">
+		</div>
+		<!-- //메인타이틀 영역 -->
+
+		<!-- 메뉴 설명 -->
+		<div class="infoBox menu-desc">
+		</div>
+		<!-- //메뉴 설명 -->
+
+		<!-- 검색조건 영역 -->
+		<div class="panelStyle">
+
+		</div>
+		<!-- 검색조건 영역 -->
+
+
+	</div>
+
+
+</html>

+ 2 - 2
src/main/webapp/WEB-INF/views/statistics/CustomerAgeOrderForm.html

@@ -49,7 +49,7 @@
 					</tr>
 					<tr>
 						<th>등급</th>
-						<td>
+						<td colspan="3">
 							<label th:if="${gradeGbList}" th:each="oneData, status : ${gradeGbList}" class="chkBox checked"><input type="checkbox" name="multiGradeGb" th:value="${oneData.cd}" th:text="${oneData.cdNm}" checked="checked"/></label>
 						</td>
 					</tr>
@@ -121,7 +121,7 @@
 						return gagaAgGrid.toAddComma(params.value);
 					}
 				},
-				{headerName: "주문수", field: "ordCnt", width: 120, cellClass: 'text-center',
+				{headerName: "주문수", field: "ordCnt", width: 150, cellClass: 'text-center',
 					cellRenderer: function(params) {
 						return gagaAgGrid.toAddComma(params.value);
 					}

+ 326 - 0
src/main/webapp/WEB-INF/views/statistics/CustomerRankingForm.html

@@ -0,0 +1,326 @@
+<!DOCTYPE html>
+<html lang="ko"
+	xmlns:th="http://www.thymeleaf.org">
+<!--
+ *******************************************************************************
+ * @source  : CustomerRankingForm.html
+ * @desc    : 구매자랭킹 Page
+ *============================================================================
+ * STYLE24
+ * Copyright(C) 2020 TSIT, All rights reserved.
+ *============================================================================
+ * VER  DATE         AUTHOR      DESCRIPTION
+ * ===  ===========  ==========  =============================================
+ * 1.0  2021.09.28   swkim       최초 작성
+ *******************************************************************************
+ -->
+	<div id="main">
+		<!-- 메인타이틀 영역 -->
+		<div class="main-title"></div>
+		<!-- //메인타이틀 영역 -->
+
+		<!-- 메뉴 설명 -->
+		<div class="infoBox menu-desc"></div>
+		<!-- //메뉴 설명 -->
+
+		<!-- 검색조건 영역 -->
+		<div class="panelStyle">
+			<form id="searchForm" name="searchForm" action="#" th:action="@{'/statistics/customer/ranking/list'}" onsubmit="$('#btnSearch').trigger('click'); return false;">
+				<input type="hidden" name="dayGb" value="D"/>
+
+				<table class="frmStyle" aria-describedby="검색조건">
+					<colgroup>
+						<col style="width:10%;"/>
+						<col style="width:25%;"/>
+						<col style="width:10%;"/>
+						<col/>
+					</colgroup>
+					<tr>
+						<th>기간<i class="required" title="필수" aria-hidden="true"></i></th>
+						<td colspan="3" id="terms"></td>
+					</tr>
+					<tr>
+						<th>디바이스</th>
+						<td colspan="3">
+							<label class="chkBox checked"><input type="checkbox" name="multiFrontGb" value="P" checked="checked"/>PC웹</label>
+							<label class="chkBox checked"><input type="checkbox" name="multiFrontGb" value="M" checked="checked"/>모바일웹</label>
+							<label class="chkBox checked"><input type="checkbox" name="multiFrontGb" value="A" checked="checked"/>APP</label>
+						</td>
+					</tr>
+					<tr>
+						<th>성별</th>
+						<td>
+							<label class="chkBox checked"><input type="checkbox" name="multiSexGb" value="G007_F" checked="checked"/>여성</label>
+							<label class="chkBox checked"><input type="checkbox" name="multiSexGb" value="G007_M" checked="checked"/>남성</label>
+							<label class="chkBox checked"><input type="checkbox" name="multiSexGb" value="G007_X" checked="checked"/>알수없음</label>
+						</td>
+						<th>연령</th>
+						<td>
+							<label class="chkBox checked"><input type="checkbox" name="multiAgeGb" value="10" checked="checked"/>10대</label>
+							<label class="chkBox checked"><input type="checkbox" name="multiAgeGb" value="20" checked="checked"/>20대</label>
+							<label class="chkBox checked"><input type="checkbox" name="multiAgeGb" value="30" checked="checked"/>30대</label>
+							<label class="chkBox checked"><input type="checkbox" name="multiAgeGb" value="40" checked="checked"/>40대</label>
+							<label class="chkBox checked"><input type="checkbox" name="multiAgeGb" value="X" checked="checked"/>기타/미상</label>
+						</td>
+					</tr>
+					<tr>
+						<th>브랜드</th>
+						<td>
+							<input type="text" class="w100" name="brandCdSearchTxt" id="brandCdSearchTxt" maxlength="20" />
+							<button type="button" class="btn icn" onclick="cfnOpenBrandListPopup('fnSetBrandInfo', 'M');"><i class="fa fa-search"></i></button>
+							<span id="brandCdTxt"></span>
+							<input type="hidden" name="brandCdList"/>
+						</td>
+						<th>매출카테고리</th>
+						<td>
+							<input type="text" class="w100" name="itemkindCdSearchTxt" id="itemkindCdSearchTxt" maxlength="20" />
+							<button type="button" class="btn icn" onclick="cfnOpenItemkindListPopup('fnSetItemkindInfo', 'M');"><i class="fa fa-search"></i></button>
+							<span id="itemkindCdTxt"></span>
+							<input type="hidden" name="itemkindCdList"/>
+						</td>
+					</tr>
+				</table>
+
+				<ul class="panelBar">
+					<li class="center">
+						<button type="button" class="btn btn-base btn-lg" id="btnSearch">조회</button>
+						<button type="button" class="btn btn-gray btn-lg" id="btnInit">초기화</button>
+					</li>
+				</ul>
+			</form>
+		</div>
+		<!-- 검색조건 영역 -->
+
+		<!-- 리스트 영역 -->
+		<div class="panelStyle">
+			<ul class="panelBar">
+				<li>
+					<button type="button" class="btn btn-default btn-lg" onclick="fnExcelDownLoad();">엑셀다운로드</button>
+				</li>
+			</ul>
+			<div id="gridList" style="width: 100%; height: 470px" class="ag-theme-balham"></div>
+		</div>
+		<!-- //리스트 영역 -->
+	</div>
+
+<style>
+.ag-header-group-text{
+	margin-left: calc(50% - 25px);
+}
+</style>
+<script th:inline="javascript">
+/*<![CDATA[*/
+	let columnDefs = [
+		{ headerName: "순위", field: "rank", width: 100, cellClass: 'text-center',
+			cellRenderer: function(params) {
+				if(params.data.custId != 'TOTAL') return  params.node.rowIndex + 1;
+				else return '';
+			}
+		},
+		{
+			headerName: "회원정보", field: "", width: 450, cellClass: 'text-center',
+			children: [
+				{headerName: "아이디(이름)", field: "custId", width: 200, cellClass: 'text-center'},
+				{headerName: "연령/성별", field: "age", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						let str1 = params.value;
+						let str2 = params.data.sexGb;
+
+						if(str1 == 'X') str1 = "알수없음";
+						else str1 = str1 + '대';
+						if(str2 == 'X') str2 = "알수없음";
+
+						if(params.data.custId != 'TOTAL') return str1 + '(' + str2 + ')';
+						else return '';
+					}
+				},
+				{headerName: "등급", field: "custGrade", width: 100, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				}
+			]
+		},
+		{
+			headerName: "주문 현황", field: "", width: 1200, cellClass: 'text-center',
+			children: [
+				{headerName: "총매출액", field: "totOrdAmt", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "주문수", field: "ordCnt", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "판매수량", field: "sellQty", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "객단가", field: "custPrice", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "보유포인트", field: "custPoint", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				}
+			]
+		}
+	];
+
+	let gridOptions = gagaAgGrid.getGridOptions(columnDefs);
+
+    gridOptions.excelStyles = [
+        {
+            id: 'text-center',
+            dataType: 'string',
+			font: {size : 10, bold: false}
+        },
+        {
+            id: 'text-left',
+            dataType: 'string',
+			font: {size : 10, bold: false}
+        },
+        {
+            id: 'text-right',
+            dataType: 'number',
+			font: {size : 10, bold: false}
+        }
+    ];
+
+    var fnExcelDownLoad = function(){
+
+    	var totalRows = gridOptions.api.getDisplayedRowCount();
+		if(totalRows==0){
+			mcxDialog.alert('조회된 내역이 없습니다.');
+			return;
+		}
+
+    	var date = new Date().format("YYYYMMDDHHmmss");
+		var params = {
+						fileName : "연령별주문현황_"+ date,
+						sheetName: "DATA"
+					 };
+		gridOptions.api.exportDataAsExcel(params);
+    }
+
+	// 브랜드 조회 팝업에서 호출
+	var fnSetBrandInfo = function(result) {
+		var arrBrandCd = [];
+		var brandCdTxt = "";
+		var bIndex = 0;
+		$('#brandCdTxt').html('');
+		$('#searchForm input[name=brandCdSearchTxt]').val('');
+
+		result.forEach(function(brand){
+			bIndex++;
+			arrBrandCd.push(brand.brandCd);
+		});
+
+		// 조회 값이 하나일 경우 화면에 코드 노출. 그 외는 갯수 처리
+		if (bIndex == 1) {
+			$('#searchForm input[name=brandCdSearchTxt]').val(arrBrandCd[0]);
+		} else {
+			brandCdTxt = bIndex + " 개";
+			$('#brandCdTxt').html(brandCdTxt);
+		}
+
+		var jsonData = JSON.stringify(arrBrandCd);
+		$("#searchForm input[name=brandCdList]").val(arrBrandCd.join(","));
+	}
+
+	// 품목 조회 팝업에서 호출
+	var fnSetItemkindInfo = function(result) {
+		var arrItemkindCd = [];
+		var itemkindCdTxt = "";
+		var bIndex = 0;
+		$('#itemkindCdTxt').html('');
+		$('#searchForm input[name=itemkindCdSearchTxt]').val('');
+
+		result.forEach(function(itemkind){
+			bIndex++;
+			arrItemkindCd.push(itemkind.itemkindCd);
+		});
+
+		// 조회 값이 하나일 경우 화면에 코드 노출. 그 외는 갯수 처리
+		if (bIndex == 1) {
+			$('#searchForm input[name=itemkindCdSearchTxt]').val(arrItemkindCd[0]);
+		} else {
+			itemkindCdTxt = bIndex + " 개";
+			$('#itemkindCdTxt').html(itemkindCdTxt);
+		}
+
+		var jsonData = JSON.stringify(arrItemkindCd);
+		$("#searchForm input[name=itemkindCdList]").val(arrItemkindCd.join(','));
+	}
+
+	// 검색
+	$('#btnSearch').on('click', function() {
+		// 입력 값 체크
+		if (!gagajf.validation($('#searchForm')))
+			return false;
+
+		gagaAgGrid.fetch($('#searchForm').prop('action'), gridOptions, '#searchForm', fnCreateTotal);
+	});
+
+	// 합계 생성
+	let fnCreateTotal = function() {
+		let len = 0;
+
+		let totInfo = {};
+		totInfo.rank     = '';
+		totInfo.custId = 'TOTAL';
+		totInfo.age = '';
+		totInfo.totOrdAmt   = 0;
+		totInfo.ordCnt  = 0;
+		totInfo.sellQty  = 0;
+		totInfo.custPrice    = 0;
+		totInfo.custPoint    = 0;
+
+		gridOptions.api.forEachNode(function(rowNode, index) {
+			if (!rowNode.group) {
+				if( typeof rowNode.data.totOrdAmt      == 'number') { totInfo.totOrdAmt       += rowNode.data.totOrdAmt      ; }
+				if( typeof rowNode.data.ordCnt  == 'number') { totInfo.ordCnt   += rowNode.data.ordCnt  ; if (rowNode.data.ordCnt > 0) len++; }
+				if( typeof rowNode.data.sellQty  == 'number') { totInfo.sellQty   += rowNode.data.sellQty  ; }
+				if( typeof rowNode.data.custPrice    == 'number') { totInfo.custPrice     += rowNode.data.custPrice    ; }
+				if( typeof rowNode.data.custPoint    == 'number') { totInfo.custPoint     += rowNode.data.custPoint    ; }
+			}
+		});
+
+		totInfo.custPrice = Math.floor(totInfo.custPrice / len);
+
+		gagaAgGrid.setPinnedRowData(gridOptions, totInfo, 'top');
+	}
+
+	// 초기화 클릭시
+	$('#btnInit').on('click', function() {
+		$('#searchForm')[0].reset();
+
+		$('#brandCdTxt').html('');
+		$('#searchForm input[name=brandCdList]').val('');
+		$('#itemkindCdTxt').html('');
+		$('#searchForm input[name=itemkindCdList]').val('');
+	});
+
+	// 엑셀다운로드
+	$('#btnExcel').on('click', function() {
+		gagaAgGrid.exportToExcel('구매자랭킹 목록', gridOptions);
+	});
+
+	$(document).ready(function() {
+		cfnCreateCalendar('#terms', 'startDt', 'endDt', true, '주문', undefined, ['btnToday']);
+		$('.btnYesterday').trigger('click');
+
+		// Create a agGrid
+		gagaAgGrid.createGrid('gridList', gridOptions);
+
+	});
+/*]]>*/
+</script>
+
+</html>