swkim 4 rokov pred
rodič
commit
69948c67fa

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

@@ -167,4 +167,16 @@ public interface TsaStatisticsDao {
 
 	Collection<Statistics> getPaymentList(Statistics statistics);
 
+	Collection<Statistics> getSubPaymentList(Statistics statistics);
+
+	Long getRemainPoint();
+
+	Long getRemainGiftCard();
+
+	Collection<Statistics> getCustomerJoinList(Statistics statistics);
+
+	Collection<Statistics> getCustomerGradOrderList(Statistics statistics);
+
+	Collection<Statistics> getCustomerAgeOrderList(Statistics statistics);
+
 }

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

@@ -106,7 +106,7 @@ public class TsaStatisticsService {
 	}
 
 	/**
-	 * 시별 주문 조회
+	 * 시별 주문 조회
 	 * @return Collection<Statistics>
 	 * @author lmc
 	 * @since 2021. 9. 16.
@@ -286,4 +286,27 @@ public class TsaStatisticsService {
 		return statisticsDao.getPaymentList(statistics);
 	}
 
+	public Collection<Statistics> getSubPaymentList(Statistics statistics) {
+		return statisticsDao.getSubPaymentList(statistics);
+	}
+
+	public long getRemainPoint() {
+		return statisticsDao.getRemainPoint();
+	}
+
+	public long getRemainGiftCard() {
+		return statisticsDao.getRemainGiftCard();
+	}
+
+	public Collection<Statistics> getCustomerJoinList(Statistics statistics) {
+		return statisticsDao.getCustomerJoinList(statistics);
+	}
+
+	public Collection<Statistics> getCustomerGradOrderList(Statistics statistics) {
+		return statisticsDao.getCustomerGradOrderList(statistics);
+	}
+
+	public Collection<Statistics> getCustomerAgeOrderList(Statistics statistics) {
+		return statisticsDao.getCustomerAgeOrderList(statistics);
+	}
 }

+ 195 - 54
src/main/java/com/style24/admin/biz/web/TsaStatisticsController.java

@@ -646,21 +646,6 @@ public class TsaStatisticsController extends TsaBaseController {
 		return mav;
 	}
 
-	/**
-	 * 결제수단별통계 화면
-	 * @return
-	 * @author swkim
-	 * @since 2021. 9. 28
-	 */
-	@GetMapping("/payment/main/form")
-	public ModelAndView paymentForm() {
-		ModelAndView mav = new ModelAndView();
-
-		mav.setViewName("statistics/PaymentForm");
-
-		return mav;
-	}
-
 	/**
 	 * 쿠폰 사용 통계 조회
 	 * author: 이명철
@@ -707,45 +692,6 @@ public class TsaStatisticsController extends TsaBaseController {
 		return mav;
 	}
 
-	/**
-	 * 결제수단별통계 조회
-	 * author: swkim
-	 * return: Collection<Statistics>
-	 * since: 2021. 9. 28.
-	 */
-	@PostMapping("/payment/main/list")
-	@ResponseBody
-	public Collection<Statistics> getPaymentList(@RequestBody Statistics statistics) {
-
-		if (!StringUtils.isBlank(statistics.getCardIdList())) {
-			try {
-				String[] arrCardId = mapper.readValue(statistics.getCardIdList(), String[].class);
-				statistics.setMultiCardId(arrCardId);
-			} catch (Exception e) {
-				throw new IllegalStateException("카드 검색조건 오류로 인해 조회되지 않았습니다.");
-			}
-		}
-
-		return statisticsService.getPaymentList(statistics);
-	}
-
-	/**
-	 * 카드 목록 화면(팝업)
-	 * @param
-	 * @return
-	 * @author swkim
-	 * @since 2021. 09. 28
-	 */
-	@GetMapping("/card/search/form")
-	public ModelAndView cardSearchForm(Card card) {
-		ModelAndView mav = new ModelAndView();
-
-		mav.addObject("params", card);
-		mav.setViewName("statistics/CardSearchForm");
-
-		return mav;
-	}
-
 	/**
 	 * 다다익선 통계 조회
 	 * author: 이명철
@@ -828,4 +774,199 @@ public class TsaStatisticsController extends TsaBaseController {
 		return statisticsService.getCardList();
 	}
 
+	/**
+	 * 결제수단별통계 화면
+	 * @return
+	 * @author swkim
+	 * @since 2021. 9. 28
+	 */
+	@GetMapping("/payment/main/form")
+	public ModelAndView paymentForm() {
+		ModelAndView mav = new ModelAndView();
+
+		mav.setViewName("statistics/PaymentForm");
+
+		return mav;
+	}
+
+	/**
+	 * 결제수단별통계 조회
+	 * author: swkim
+	 * return: Collection<Statistics>
+	 * since: 2021. 9. 28.
+	 */
+	@PostMapping("/payment/main/list")
+	@ResponseBody
+	public Collection<Statistics> getPaymentList(@RequestBody Statistics statistics) {
+
+		if (!StringUtils.isBlank(statistics.getCardIdList())) {
+			try {
+				String[] arrCardId = mapper.readValue(statistics.getCardIdList(), String[].class);
+				statistics.setMultiCardId(arrCardId);
+			} catch (Exception e) {
+				throw new IllegalStateException("카드 검색조건 오류로 인해 조회되지 않았습니다.");
+			}
+		}
+
+		return statisticsService.getPaymentList(statistics);
+	}
+
+	/**
+	 * 카드 목록 화면(팝업)
+	 * @param
+	 * @return
+	 * @author swkim
+	 * @since 2021. 09. 28
+	 */
+	@GetMapping("/card/search/form")
+	public ModelAndView cardSearchForm(Card card) {
+		ModelAndView mav = new ModelAndView();
+
+		mav.addObject("params", card);
+		mav.setViewName("statistics/CardSearchForm");
+
+		return mav;
+	}
+
+	/**
+	 * 부결제수단별통계 화면
+	 * @return
+	 * @author swkim
+	 * @since 2021. 9. 28
+	 */
+	@GetMapping("/payment/sub/form")
+	public ModelAndView subPaymentForm() {
+		ModelAndView mav = new ModelAndView();
+
+		// 포인트유형
+		mav.addObject("pointGbList", rendererService.getCommonCodeList("G069"));
+
+		// 상품권유형
+		mav.addObject("giftCardGbList", rendererService.getCommonCodeList("G074"));
+
+		// 포인트잔액
+		mav.addObject("remainPoint", statisticsService.getRemainPoint());
+
+		// 상품권잔액
+		mav.addObject("remainGiftCard", statisticsService.getRemainGiftCard());
+
+		mav.setViewName("statistics/SubPaymentForm");
+
+		return mav;
+	}
+
+	/**
+	 * 결제수단별통계 조회
+	 * author: swkim
+	 * return: Collection<Statistics>
+	 * since: 2021. 9. 28.
+	 */
+	@PostMapping("/payment/sub/list")
+	@ResponseBody
+	public Collection<Statistics> getSubPaymentList(@RequestBody Statistics statistics) {
+
+		return statisticsService.getSubPaymentList(statistics);
+	}
+
+	/**
+	 * 가입현황 화면
+	 * @return
+	 * @author swkim
+	 * @since 2021. 9. 28
+	 */
+	@GetMapping("/customer/join/form")
+	public ModelAndView customerJoinForm() {
+		ModelAndView mav = new ModelAndView();
+
+		mav.setViewName("statistics/CustomerJoinForm");
+
+		return mav;
+	}
+
+	/**
+	 * 가입현황 조회
+	 * author: swkim
+	 * return: Collection<Statistics>
+	 * since: 2021. 9. 28.
+	 */
+	@PostMapping("/customer/join/list")
+	@ResponseBody
+	public Collection<Statistics> getCustomerJoinList(@RequestBody Statistics statistics) {
+
+		return statisticsService.getCustomerJoinList(statistics);
+	}
+
+	/**
+	 * 등급별주문현황 화면
+	 * @return
+	 * @author swkim
+	 * @since 2021. 9. 28
+	 */
+	@GetMapping("/customer/grade/order/form")
+	public ModelAndView customerGradOrderForm() {
+		ModelAndView mav = new ModelAndView();
+
+		mav.setViewName("statistics/CustomerGradeOrderForm");
+
+		return mav;
+	}
+
+	/**
+	 * 등급별주문현황 조회
+	 * author: swkim
+	 * return: Collection<Statistics>
+	 * since: 2021. 9. 28.
+	 */
+	@PostMapping("/customer/grade/order/list")
+	@ResponseBody
+	public Collection<Statistics> getCustomerGradOrderList(@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.getCustomerGradOrderList(statistics);
+	}
+
+	/**
+	 * 연령별주문현황 화면
+	 * @return
+	 * @author swkim
+	 * @since 2021. 9. 28
+	 */
+	@GetMapping("/customer/age/order/form")
+	public ModelAndView customerAgeOrderForm() {
+		ModelAndView mav = new ModelAndView();
+
+		// 회원등급
+		mav.addObject("gradeGbList", rendererService.getAvailCommonCodeList("G110"));
+		mav.setViewName("statistics/CustomerAgeOrderForm");
+
+		return mav;
+	}
+
+	/**
+	 * 연령별주문현황 조회
+	 * author: swkim
+	 * return: Collection<Statistics>
+	 * since: 2021. 9. 28.
+	 */
+	@PostMapping("/customer/age/order/list")
+	@ResponseBody
+	public Collection<Statistics> getCustomerAgeOrderList(@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.getCustomerAgeOrderList(statistics);
+	}
 }

+ 39 - 3
src/main/java/com/style24/persistence/domain/Statistics.java

@@ -152,7 +152,7 @@ public class Statistics extends TscBaseDomain {
 	private int sellFeeAmt;				// 수수료(실판매금액 * 판매수수료율)
 	private int totAmt10;				// 정상
 	private int totAmt20;				// 이월
-	private int amtRate10;				// 정상비
+	private double amtRate10;			// 정상비
 	private String mdId;				// 담당MD아이디
 	private String mdNm;				// 담당MD명
 	private String formalGb;			// 이월구분
@@ -167,8 +167,8 @@ public class Statistics extends TscBaseDomain {
 
 	private long clmAmt;      //클래임금액
 	private int clmQty;       //클랭미수량
-	private int amtRate;      //금액비
-	private int clmRate;      //클래임율
+	private double amtRate;      //금액비
+	private double clmRate;      //클래임율
 	private int rtnQty;       //반품수량
 	private long rtnAmt;      //반품금액
 	private int chgQty;       //교환수량
@@ -228,4 +228,40 @@ public class Statistics extends TscBaseDomain {
 
 	@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
 	private String[] multiCardId;
+
+	private long pntGive;
+	private int pntOrdCnt;
+	private long pntUse;
+	private int giftRegCnt;
+	private int giftOrdCnt;
+	private long giftUse;
+	private String pointGb;
+	private String giftCardGb;
+
+	private int allCnt;
+	private int realCnt;
+	private int dormCnt;
+	private int vipCnt;
+	private int goldCnt;
+	private int silverCnt;
+	private int bronzeCnt;
+	private int welcomeCnt;
+	private int joinCnt;
+	private int drJoinCnt;
+	private int afJoinCnt;
+	private int chgDormCnt;
+	private int rmDormCnt;
+	private int seceedCnt;
+
+	private int priority;
+	private String custGrade;
+	private double avgOrdCnt;
+	private double avgSellQty;
+
+	private String age;
+	private String sexGb;
+
+	@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
+	private String[] multiGradeGb;
+
 }

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

@@ -1882,4 +1882,207 @@
 		GROUP BY DAY
 	</select>
 
+	<!-- 부결제수단별통계 목록 -->
+	<select id="getSubPaymentList" parameterType="Statistics" resultType="Statistics">
+		/* TsaStatistics.getSubPaymentList */
+		SELECT
+		<choose>
+			<when test='dayGb == "W"'> <!-- 주별 -->
+				CONCAT(MONTH(DAY), '월 ', WEEK(DAY,5) - WEEK(DATE_SUB(DAY, INTERVAL DAYOFMONTH(DAY) - 1 DAY), 5) + 1, '주') AS DAY
+			</when>
+			<when test='dayGb == "M"'> <!-- 월별 -->
+				DATE_FORMAT(DAY,'%Y-%m')                          AS DAY
+			</when>
+			<otherwise> <!-- 일별 -->
+				DATE_FORMAT(DAY,'%Y-%m-%d')                       AS DAY
+			</otherwise>
+		</choose>
+			, SUM(A.PNT_GIVE) AS PNT_GIVE -- 포인트적립액
+			, SUM(A.PNT_ORD_CNT) AS PNT_ORD_CNT -- 포인트사용주문수
+			, SUM(A.PNT_USE) AS PNT_USE -- 포인트사용액
+			, SUM(A.GIFT_REG_CNT) AS GIFT_REG_CNT -- 상품권등록매수
+			, SUM(A.GIFT_ORD_CNT) AS GIFT_ORD_CNT -- 상품권주문수
+			, SUM(A.GIFT_USE) AS GIFT_USE -- 상품권사용액
+		FROM TB_STAT_SUB_PAY A
+		WHERE A.DAY <![CDATA[>=]]> STR_TO_DATE(#{startDt},'%Y-%m-%d')
+		  AND A.DAY <![CDATA[<]]> DATE_ADD(STR_TO_DATE(#{endDt},'%Y-%m-%d'), INTERVAL 1 DAY)
+		<choose>
+			<when test='pointGb != null and pointGb != "" and giftCardGb != null and giftCardGb != ""'>
+				AND OCCUR_GB IN(#{pointGb}, #{giftCardGb})
+			</when>
+			<when test='pointGb != null and pointGb != ""'>
+				AND OCCUR_GB = #{pointGb}
+			</when>
+			<when test='giftCardGb != null and giftCardGb != ""'>
+				AND OCCUR_GB = {giftCardGb}
+			</when>
+		</choose>
+		<choose>
+			<when test='dayGb == "W"'> <!-- 주별 -->
+				GROUP  BY CONCAT(MONTH(DAY), '월 ', WEEK(DAY,5) - WEEK(DATE_SUB(DAY, INTERVAL DAYOFMONTH(DAY) - 1 DAY), 5) + 1, '주')
+			</when>
+			<when test='dayGb == "M"'> <!-- 월별 -->
+				GROUP  BY DATE_FORMAT(DAY,'%Y-%m')
+			</when>
+			<otherwise> <!-- 일별 -->
+				GROUP  BY DATE_FORMAT(DAY,'%Y-%m-%d')
+			</otherwise>
+		</choose>
+	</select>
+
+	<!-- 포인트잔액 -->
+	<select id="getRemainPoint" resultType="java.lang.Long">
+		/* TsaStatistics.getRemainPoint */
+		SELECT
+			SUM(RM_PNT_AMT) AS RM_PNT_AMT
+		FROM TB_CUST_POINT A
+		WHERE A.EXP_CMP_DT IS NULL
+	</select>
+
+	<!-- 포인트잔액 -->
+	<select id="getRemainGiftCard" resultType="java.lang.Long">
+		/* TsaStatistics.getRemainGiftCard */
+		SELECT
+		SUM(RM_GFCD_AMT) AS RM_GFCD_AMT
+		FROM TB_CUST_GIFTCARD A
+		WHERE DATE_FORMAT(USE_EXP_DATE, '%Y%m%d') &lt; NOW()
+	</select>
+
+	<!-- 가입통계 -->
+	<select id="getCustomerJoinList" parameterType="Statistics" resultType="Statistics">
+		/* TsaStatistics.getCustomerJoinList */
+		SELECT
+	<choose>
+		<when test='dayGb == "W"'> <!-- 주별 -->
+			CONCAT(MONTH(DAY), '월 ', WEEK(DAY,5) - WEEK(DATE_SUB(DAY, INTERVAL DAYOFMONTH(DAY) - 1 DAY), 5) + 1, '주') AS DAY
+		</when>
+		<when test='dayGb == "M"'> <!-- 월별 -->
+			DATE_FORMAT(DAY,'%Y-%m')                          AS DAY
+		</when>
+		<otherwise> <!-- 일별 -->
+			DATE_FORMAT(DAY,'%Y-%m-%d')                       AS DAY
+		</otherwise>
+	</choose>
+			, MAX(ALL_CNT) AS ALL_CNT
+			, MAX(REAL_CNT) AS REAL_CNT
+			, MAX(DORM_CNT) AS DORM_CNT
+			, MAX(VIP_CNT) AS VIP_CNT
+			, MAX(GOLD_CNT) AS GOLD_CNT
+			, MAX(SILVER_CNT) AS SILVER_CNT
+			, MAX(BRONZE_CNT) AS BRONZE_CNT
+			, MAX(WELCOME_CNT) AS WELCOME_CNT
+			, SUM(JOIN_CNT) AS JOIN_CNT
+			, SUM(DR_JOIN_CNT) AS DR_JOIN_CNT
+			, SUM(AF_JOIN_CNT) AS AF_JOIN_CNT
+			, SUM(CHG_DORM_CNT) AS CHG_DORM_CNT
+			, SUM(RM_DORM_CNT) AS RM_DORM_CNT
+			, SUM(SECEED_CNT) AS SECEED_CNT
+		FROM TB_STAT_CUST
+		WHERE DAY <![CDATA[>=]]> STR_TO_DATE(#{startDt},'%Y-%m-%d')
+		  AND DAY <![CDATA[<]]> DATE_ADD(STR_TO_DATE(#{endDt},'%Y-%m-%d'), INTERVAL 1 DAY)
+	<if test="multiSexGb != null">
+		/* 성별구분 */
+		<foreach collection="multiSexGb" item="item" index="index"  open="AND SEX_GB IN (" close=")" separator=",">#{item}</foreach>
+	</if>
+	<if test="multiAgeGb != null">
+		/* 연령구분 */
+		<foreach collection="multiAgeGb" item="item" index="index"  open="AND AGE IN (" close=")" separator=",">#{item}</foreach>
+	</if>
+	<choose>
+		<when test='dayGb == "W"'> <!-- 주별 -->
+			GROUP  BY CONCAT(MONTH(DAY), '월 ', WEEK(DAY,5) - WEEK(DATE_SUB(DAY, INTERVAL DAYOFMONTH(DAY) - 1 DAY), 5) + 1, '주')
+		</when>
+		<when test='dayGb == "M"'> <!-- 월별 -->
+			GROUP  BY DATE_FORMAT(DAY,'%Y-%m')
+		</when>
+		<otherwise> <!-- 일별 -->
+			GROUP  BY DATE_FORMAT(DAY,'%Y-%m-%d')
+		</otherwise>
+	</choose>
+		ORDER BY DAY DESC
+	</select>
+
+	<!-- 등급별주문현황 -->
+	<select id="getCustomerGradOrderList" parameterType="Statistics" resultType="Statistics">
+		/* TsaStatistics.getCustomerGradOrderList */
+		SELECT
+			CASE WHEN A.CUST_GRADE = 'G110_10' THEN 1
+				WHEN A.CUST_GRADE = 'G110_20' THEN 2
+				WHEN A.CUST_GRADE = 'G110_30' THEN 3
+				WHEN A.CUST_GRADE = 'G110_40' THEN 4
+				WHEN A.CUST_GRADE = 'G110_50' THEN 5
+			ELSE 6 END AS PRIORITY
+			, FN_GET_CODE_NM('G110', A.CUST_GRADE) AS CUST_GRADE
+			, SUM(A.ORD_AMT - A.CNCL_AMT - A.RTN_AMT) AS TOT_ORD_AMT -- 총매출액
+			, SUM(A.ORD_AMT) AS ORD_AMT -- 매출액
+			, SUM(A.CNCL_AMT + A.RTN_AMT) AS CNCL_AMT -- 취/반품액
+			, SUM(A.ORD_CNT) AS ORD_CNT -- 주문수
+			, SUM(A.CNCL_QTY + A.RTN_QTY) AS CNCL_QTY -- 취/반품갯수
+			, ROUND(CEIL(AVG(A.ORD_CNT) * 10) / 10, 1) AS AVG_ORD_CNT -- 평균주문수
+			, ROUND(CEIL(AVG(A.SELL_QTY) * 10) / 10, 1) AS AVG_SELL_QTY -- 평균주문상품개수
+			, FLOOR(SUM(A.ORD_AMT) / SUM(A.ORD_CNT)) AS CUST_PRICE -- 객단가
+		FROM TB_STAT_CUST_ORD A
+		WHERE DAY <![CDATA[>=]]> STR_TO_DATE(#{startDt},'%Y-%m-%d')
+			AND DAY <![CDATA[<]]> DATE_ADD(STR_TO_DATE(#{endDt},'%Y-%m-%d'), INTERVAL 1 DAY)
+		<if test="multiFrontGb != null">
+			/* 디바이스 */
+			<foreach collection="multiFrontGb" item="item" index="index"  open="AND FRONT_GB IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+		<if test="multiSexGb != null">
+			/* 성별구분 */
+			<foreach collection="multiSexGb" item="item" index="index"  open="AND SEX_GB IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+		<if test="multiAgeGb != null">
+			/* 연령구분 */
+			<foreach collection="multiAgeGb" item="item" index="index"  open="AND AGE 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 A.CUST_GRADE
+		ORDER BY PRIORITY
+	</select>
+
+	<!-- 등급별주문현황 -->
+	<select id="getCustomerAgeOrderList" parameterType="Statistics" resultType="Statistics">
+		/* TsaStatistics.getCustomerAgeOrderList */
+		SELECT
+			CASE WHEN A.AGE != 'X' THEN CONCAT(A.AGE, '대') ELSE '50대이상/기타' END AS AGE
+			, FN_GET_CODE_NM('G007', A.SEX_GB) AS SEX_GB
+			, SUM(A.ORD_AMT - A.CNCL_AMT - A.RTN_AMT) AS TOT_ORD_AMT -- 총매출액
+			, SUM(A.ORD_AMT) AS ORD_AMT -- 매출액
+			, SUM(A.CNCL_AMT + A.RTN_AMT) AS CNCL_AMT -- 취/반품액
+			, SUM(A.ORD_CNT) AS ORD_CNT -- 주문수
+			, SUM(A.CNCL_QTY + A.RTN_QTY) AS CNCL_QTY -- 취/반품갯수
+			, ROUND(CEIL(AVG(A.ORD_CNT) * 10) / 10, 1) AS AVG_ORD_CNT -- 평균주문수
+			, ROUND(CEIL(AVG(A.SELL_QTY) * 10) / 10, 1) AS AVG_SELL_QTY -- 평균주문상품개수
+			, FLOOR(SUM(A.ORD_AMT) / SUM(A.ORD_CNT)) AS CUST_PRICE -- 객단가
+		FROM TB_STAT_CUST_ORD A
+		WHERE DAY <![CDATA[>=]]> STR_TO_DATE(#{startDt},'%Y-%m-%d')
+			AND DAY <![CDATA[<]]> DATE_ADD(STR_TO_DATE(#{endDt},'%Y-%m-%d'), INTERVAL 1 DAY)
+		<if test="multiFrontGb != null">
+			/* 디바이스 */
+			<foreach collection="multiFrontGb" item="item" index="index"  open="AND FRONT_GB IN (" close=")" separator=",">#{item}</foreach>
+		</if>
+		<if test="multiGradeGb != null">
+			/* 등급 */
+			<foreach collection="multiGradeGb" item="item" index="index"  open="AND CUST_GRADE 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 A.AGE, A.SEX_GB
+		ORDER BY A.AGE, A.SEX_GB
+	</select>
+
 </mapper>

+ 1 - 1
src/main/webapp/WEB-INF/views/statistics/BestTradingForm.html

@@ -95,7 +95,7 @@
 						<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="itemkindTxt"></span>
+							<span id="itemkindCdTxt"></span>
 							<input type="hidden" name="itemkindCdList"/>
 						</td>
 					</tr>

+ 1 - 1
src/main/webapp/WEB-INF/views/statistics/BrandTradingForm.html

@@ -89,7 +89,7 @@
 						<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="itemkindTxt"></span>
+							<span id="itemkindCdTxt"></span>
 							<input type="hidden" name="itemkindCdList"/>
 						</td>
 					</tr>

+ 1 - 1
src/main/webapp/WEB-INF/views/statistics/ChannelTradingForm.html

@@ -71,7 +71,7 @@
 						<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="itemkindTxt"></span>
+							<span id="itemkindCdTxt"></span>
 							<input type="hidden" name="itemkindCdList"/>
 						</td>
 					</tr>

+ 1 - 1
src/main/webapp/WEB-INF/views/statistics/ClaimTradingForm.html

@@ -82,7 +82,7 @@
 						<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="itemkindTxt"></span>
+							<span id="itemkindCdTxt"></span>
 							<input type="hidden" name="itemkindCdList"/>
 						</td>
 					</tr>

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

@@ -0,0 +1,310 @@
+<!DOCTYPE html>
+<html lang="ko"
+	xmlns:th="http://www.thymeleaf.org">
+<!--
+ *******************************************************************************
+ * @source  : CustomerAgeOrderForm.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/age/order/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 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>
+					<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: "age", width: 100, cellClass: 'text-center' },
+		{ headerName: "성별", field: "sexGb", width: 100, cellClass: 'text-center' },
+		{
+			headerName: "주문 현황", field: "", width: 1200, cellClass: 'text-center',
+			children: [
+				{headerName: "총매출액(A+B)", field: "totOrdAmt", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "매출액(A)", field: "ordAmt", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "취/반품액(B)", field: "cnclAmt", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "주문수", field: "ordCnt", width: 120, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "취/반품갯수", field: "cnclQty", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "기간평균주문수", field: "avgOrdCnt", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "평균주문상품개수", field: "avgSellQty", 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);
+					}
+				}
+			]
+		}
+	];
+
+	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.age     = '';
+		totInfo.sexGb = 'TOTAL';
+		totInfo.totOrdAmt   = 0;
+		totInfo.ordAmt     = 0;
+		totInfo.cnclAmt = 0;
+		totInfo.ordCnt  = 0;
+		totInfo.cnclQty  = 0;
+		totInfo.avgOrdCnt     = 0;
+		totInfo.avgSellQty    = 0;
+		totInfo.custPrice    = 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.ordAmt     == 'number') { totInfo.ordAmt      += rowNode.data.ordAmt     ; }
+				if( typeof rowNode.data.cnclAmt == 'number') { totInfo.cnclAmt  += rowNode.data.cnclAmt ; }
+				if( typeof rowNode.data.ordCnt  == 'number') { totInfo.ordCnt   += rowNode.data.ordCnt  ; if (rowNode.data.ordCnt > 0) len++; }
+				if( typeof rowNode.data.cnclQty  == 'number') { totInfo.cnclQty   += rowNode.data.cnclQty  ; }
+				if( typeof rowNode.data.avgOrdCnt  == 'number') { totInfo.avgOrdCnt   += rowNode.data.avgOrdCnt  ; }
+				if( typeof rowNode.data.avgSellQty     == 'number') { totInfo.avgSellQty      += rowNode.data.avgSellQty     ; }
+				if( typeof rowNode.data.custPrice    == 'number') { totInfo.custPrice     += rowNode.data.custPrice    ; }
+			}
+		});
+
+		totInfo.avgOrdCnt = (Math.round(totInfo.avgOrdCnt / len * 10) / 10);
+		totInfo.avgSellQty = (Math.round(totInfo.avgSellQty / len * 10) / 10);
+		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>

+ 402 - 0
src/main/webapp/WEB-INF/views/statistics/CustomerGradeOrderForm.html

@@ -0,0 +1,402 @@
+<!DOCTYPE html>
+<html lang="ko"
+	xmlns:th="http://www.thymeleaf.org">
+<!--
+ *******************************************************************************
+ * @source  : CustomerGradeOrderForm.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/grade/order/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" id="chartDiv">
+			<div id="chart" class="chartUnit"></div>
+		</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: "custGrade", width: 100, cellClass: 'text-center' },
+		{
+			headerName: "주문 현황", field: "", width: 1200, cellClass: 'text-center',
+			children: [
+				{headerName: "총매출액(A+B)", field: "totOrdAmt", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "매출액(A)", field: "ordAmt", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "취/반품액(B)", field: "cnclAmt", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "주문수", field: "ordCnt", width: 120, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "취/반품갯수", field: "cnclQty", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "기간평균주문수", field: "avgOrdCnt", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "평균주문상품개수", field: "avgSellQty", 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);
+					}
+				}
+			]
+		}
+	];
+
+	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() {
+
+		// Draw chart
+		fnDrawChart(gagaAgGrid.getAllRowData(gridOptions));
+
+		let len = 0;
+
+		let totInfo = {};
+		totInfo.custGrade     = 'TOTAL';
+		totInfo.totOrdAmt   = 0;
+		totInfo.ordAmt     = 0;
+		totInfo.cnclAmt = 0;
+		totInfo.ordCnt  = 0;
+		totInfo.cnclQty  = 0;
+		totInfo.avgOrdCnt     = 0;
+		totInfo.avgSellQty    = 0;
+		totInfo.custPrice    = 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.ordAmt     == 'number') { totInfo.ordAmt      += rowNode.data.ordAmt     ; }
+				if( typeof rowNode.data.cnclAmt == 'number') { totInfo.cnclAmt  += rowNode.data.cnclAmt ; }
+				if( typeof rowNode.data.ordCnt  == 'number') { totInfo.ordCnt   += rowNode.data.ordCnt  ; if (rowNode.data.ordCnt > 0) len++; }
+				if( typeof rowNode.data.cnclQty  == 'number') { totInfo.cnclQty   += rowNode.data.cnclQty  ; }
+				if( typeof rowNode.data.avgOrdCnt  == 'number') { totInfo.avgOrdCnt   += rowNode.data.avgOrdCnt  ; }
+				if( typeof rowNode.data.avgSellQty     == 'number') { totInfo.avgSellQty      += rowNode.data.avgSellQty     ; }
+				if( typeof rowNode.data.custPrice    == 'number') { totInfo.custPrice     += rowNode.data.custPrice    ; }
+			}
+		});
+
+		totInfo.avgOrdCnt = (Math.round(totInfo.avgOrdCnt / len * 10) / 10);
+		totInfo.avgSellQty = (Math.round(totInfo.avgSellQty / len * 10) / 10);
+		totInfo.custPrice = Math.floor(totInfo.custPrice / len);
+
+		gagaAgGrid.setPinnedRowData(gridOptions, totInfo, 'top');
+	}
+
+	// 그래프 그리기
+	var chart1;
+	var fnDrawChart = function(data) {
+		let xList = [];
+		let ordAmtList = [];
+
+		$(data).each(function(idx, item) {
+			xList.push(item.custGrade);
+			ordAmtList.push(item.ordAmt);
+		});
+
+		chart1 = c3.generate({
+			bindto: "#chart",
+			padding: {
+				bottom: 20 //adjust chart padding bottom
+			},
+			data: {
+				x: 'x',
+				json: {
+					x: xList,
+					등급별매출액: ordAmtList
+				},
+				types: {
+					등급별매출액: 'bar'
+				}/* ,
+					regions: {
+						'data1': [
+							{
+								'start': 1,
+								'end': 2,
+								'style': 'dashed'
+							}, {
+								'start': 3
+							}
+						]
+					} */
+			},
+			color: {
+				pattern: ['#48C9B0', '#FF7043', '#FF7043']
+			},
+			legend: { padding: 15 }, //범례 item 우측 간격
+			axis: {
+				x: {
+					type: 'category',
+					padding: { left: 0.5, right: 0.5 }
+				}/* ,
+					y: {
+						tick: {
+							format: function(d) { return Number(d).addComma() + 'K'; }
+						}
+					} */
+			},
+			tooltip: {
+				format: {
+					title: function (d) {
+						return '등급별 매출액 Chart';
+					}
+				}
+			}/* ,
+				bar: {
+					width: { ratio: 0.2 } // 막대 폭 20%로 조절
+				} */
+		});
+	}
+
+	// LNB 또는 GNB 클릭시 차트 넓이 변경
+	var chartResize = function() {
+		setTimeout(function () {
+			// 모든 차트 ID객체에 적용
+			chart1.resize();
+		}, 300);
+	}
+
+	// 초기화 클릭시
+	$('#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>

+ 367 - 0
src/main/webapp/WEB-INF/views/statistics/CustomerJoinForm.html

@@ -0,0 +1,367 @@
+<!DOCTYPE html>
+<html lang="ko"
+	xmlns:th="http://www.thymeleaf.org">
+<!--
+ *******************************************************************************
+ * @source  : CustomerJoinForm.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/join/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 style="width:25%;"/>
+						<col style="width:10%;"/>
+						<col style="width:20%;"/>
+					</colgroup>
+					<tr>
+						<th>기간<i class="required" title="필수" aria-hidden="true"></i></th>
+						<td colspan="5" id="terms">
+						</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 colspan="3">
+							<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>
+				</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" id="chartDiv">
+			<div id="chart" class="chartUnit"></div>
+		</div>
+		<!-- //차트영역 -->
+
+		<!-- 리스트 영역 -->
+		<div class="panelStyle">
+			<!-- 버튼 배치 영역 -->
+			<ul class="panelBar">
+				<li class="left">
+					<button type="button" class="btn btn-default btn-lg" id="btnExcel">엑셀다운로드</button>
+				</li>
+				<li class="right">
+					<span class="btnGroup marR10">
+						<button type="button" class="btn btn-default btn-lg active" id="dayGbD" onclick="fnSetDayGb('D');">일별</button>
+						<button type="button" class="btn btn-default btn-lg" id="dayGbW" onclick="fnSetDayGb('W');">주별</button>
+						<button type="button" class="btn btn-default btn-lg" id="dayGbM" onclick="fnSetDayGb('M');">월별</button>
+					</span>
+				</li>
+			</ul>
+			<!-- //버튼 배치 영역 -->
+
+			<div id="gridList" style="width: 100%; height: 470px" class="ag-theme-balham"></div>
+		</div>
+		<!-- //리스트 영역 -->
+	</div>
+
+<script th:inline="javascript">
+/*<![CDATA[*/
+	let columnDefs = [
+		{ headerName: "기간", field: "day", width: 100, cellClass: 'text-center' },
+		{
+			headerName: "전체회원", field: "", width: 450, cellClass: 'text-center',
+			children: [
+				{headerName: "전체회원", field: "allCnt", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "실회원", field: "realCnt", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "휴면회원", field: "dormCnt", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				}
+			]
+		},
+		{
+			headerName: "등급별회원수(실회원)", field: "", width: 600, cellClass: 'text-center',
+			children: [
+				{headerName: "VIP", field: "vipCnt", width: 120, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "GOLD", field: "goldCnt", width: 120, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "SILVER", field: "silverCnt", width: 120, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "BRONZE", field: "bronzeCnt", width: 120, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "WELCOME", field: "welcomeCnt", width: 120, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				}
+			]
+		},
+		{
+			headerName: "가입", field: "", width: 450, cellClass: 'text-center',
+			children: [
+				{headerName: "가입수", field: "joinCnt", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "직방문", field: "drJoinCnt", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "제휴", field: "afJoinCnt", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				}
+			]
+		},
+		{
+			headerName: "휴면/탈퇴", field: "", width: 450, cellClass: 'text-center',
+			children: [
+				{headerName: "휴면전환", field: "chgDormCnt", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "휴면해제", field: "rmDormCnt", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "탈퇴", field: "seceedCnt", width: 150, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				}
+			]
+		}
+	];
+
+	let gridOptions = gagaAgGrid.getGridOptions(columnDefs);
+
+	gridOptions.autoGroupColumnDef = {
+			headerName: "일자",
+			field: "grouping",
+			width: 200,
+			cellRendererParams: {
+				suppressCount: true
+			}
+		};
+
+	// for expand everything
+	gridOptions.groupDefaultExpanded = -1;
+
+	// 검색
+	$('#btnSearch').on('click', function() {
+		// 입력 값 체크
+		if (!gagajf.validation($('#searchForm')))
+			return false;
+
+		gagaAgGrid.fetch($('#searchForm').prop('action'), gridOptions, '#searchForm', fnCreateTotal);
+	});
+
+	// 합계 생성
+	let fnCreateTotal = function() {
+		// Draw chart
+		fnDrawChart(gagaAgGrid.getAllRowData(gridOptions));
+
+		let tmpData = gagaAgGrid.getAllRowData(gridOptions);
+		let tmpLen = 0;
+
+		let allCnt = tmpData[tmpLen].allCnt;
+		let realCnt = tmpData[tmpLen].realCnt;
+		let dormCnt = tmpData[tmpLen].dormCnt;
+		let vipCnt = tmpData[tmpLen].vipCnt;
+		let goldCnt = tmpData[tmpLen].goldCnt;
+		let silverCnt = tmpData[tmpLen].silverCnt;
+		let bronzeCnt = tmpData[tmpLen].bronzeCnt;
+		let welcomeCnt = tmpData[tmpLen].welcomeCnt;
+		let joinCnt = 0;
+		let drJoinCnt = 0;
+		let afJoinCnt = 0;
+		let chgDormCnt = 0;
+		let rmDormCnt = 0;
+		let seceedCnt = 0;
+
+		gridOptions.api.forEachNode(function(rowNode, index) {
+			if (!rowNode.group) {
+				if (typeof rowNode.data.joinCnt == 'number') { joinCnt += rowNode.data.joinCnt; }
+				if (typeof rowNode.data.drJoinCnt == 'number') { drJoinCnt += rowNode.data.drJoinCnt; }
+				if (typeof rowNode.data.afJoinCnt == 'number') { afJoinCnt += rowNode.data.afJoinCnt; }
+				if (typeof rowNode.data.chgDormCnt == 'number') { chgDormCnt += rowNode.data.chgDormCnt; }
+				if (typeof rowNode.data.rmDormCnt == 'number') { rmDormCnt += rowNode.data.rmDormCnt; }
+				if (typeof rowNode.data.seceedCnt == 'number') { seceedCnt += rowNode.data.seceedCnt; }
+			}
+		});
+
+		let data = {
+			day: 'TOTAL',
+			allCnt: allCnt, realCnt: realCnt, dormCnt: dormCnt,
+			vipCnt: vipCnt, goldCnt: goldCnt, silverCnt: silverCnt,
+			bronzeCnt: bronzeCnt, welcomeCnt: welcomeCnt, joinCnt: joinCnt,
+			drJoinCnt: drJoinCnt, afJoinCnt: afJoinCnt, chgDormCnt: chgDormCnt,
+			rmDormCnt: rmDormCnt, seceedCnt: seceedCnt
+		};
+
+		gagaAgGrid.setPinnedRowData(gridOptions, data, 'top');
+	}
+
+	// 그래프 그리기
+	var chart1;
+	var fnDrawChart = function(data) {
+		let xList = [];
+		let totCntList = [];
+
+		for(var i = (data.length - 1); i > -1; i--){
+			if ($('#dayGbD').hasClass('active')) {
+				xList.push(data[i].day.toDate('YYYY-MM-DD').format('MM-DD'));
+			} else {
+				xList.push(data[i].day);
+			}
+			totCntList.push(data[i].allCnt);
+		}
+
+		chart1 = c3.generate({
+			bindto: "#chart",
+			padding: {
+				bottom: 20 //adjust chart padding bottom
+			},
+			data: {
+				x: 'x',
+				json: {
+					x: xList,
+					회원수: totCntList
+				},
+				types: {
+					x: 'line',
+					회원수: 'line'
+				}
+			},
+			axis : {
+				x: {
+					type: 'category',
+					padding: { left: 0.5, right: 0.5 }
+				},
+				y : {
+					tick: {
+						format: d3.format(",")
+					}
+				}
+			},
+			color: {
+				pattern: ['#48C9B0', '#FF7043']
+			},
+			legend: { padding: 15 }, //범례 item 우측 간격
+			tooltip: {
+				format: {
+					title: function (d) {
+						return '가입 통계 Chart';
+					},
+				}
+			}
+		});
+	}
+
+	// LNB 또는 GNB 클릭시 차트 넓이 변경
+	var chartResize = function() {
+		setTimeout(function () {
+			// 모든 차트 ID객체에 적용
+			chart1.resize();
+		}, 300);
+	}
+
+	// 초기화 클릭시
+	$('#btnInit').on('click', function() {
+		$('#searchForm')[0].reset();
+
+		$('#cardIdTxt').html('');
+		$('#searchForm input[name=cardIdList]').val('');
+	});
+
+	// 엑셀다운로드
+	$('#btnExcel').on('click', function() {
+		gagaAgGrid.exportToExcel('결제수단별통계 목록', gridOptions);
+	});
+
+	// 일자구분 변경 시
+	var fnSetDayGb = function(dayGb) {
+		$('#searchForm input[name=dayGb]').val(dayGb);
+		$('#dayGbD').removeClass('active');
+		$('#dayGbW').removeClass('active');
+		$('#dayGbM').removeClass('active');
+		$('#dayGb' + dayGb).addClass('active');
+		$('#btnSearch').trigger('click');
+	}
+
+	$(document).ready(function() {
+		cfnCreateCalendar('#terms', 'startDt', 'endDt', true, '주문', undefined, ['btnToday']);
+		$('.btnRecentWeek').trigger('click');
+
+		// Create a agGrid
+		gagaAgGrid.createGrid('gridList', gridOptions);
+
+	});
+/*]]>*/
+</script>
+
+</html>

+ 1 - 1
src/main/webapp/WEB-INF/views/statistics/DailyOrderForm.html

@@ -90,7 +90,7 @@
 						<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="itemkindTxt"></span>
+							<span id="itemkindCdTxt"></span>
 							<input type="hidden" name="itemkindList"/>
 						</td>
 					</tr>

+ 1 - 1
src/main/webapp/WEB-INF/views/statistics/ExtmallTradingForm.html

@@ -64,7 +64,7 @@
 						<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="itemkindTxt"></span>
+							<span id="itemkindCdTxt"></span>
 							<input type="hidden" name="itemkindCdList"/>
 						</td>
 					</tr>

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

@@ -69,7 +69,7 @@
 						</td>
 						<th>정상/이월구분</th>
 						<td>
-							<label th:if="${formalGbList}" th:each="oneData, status : ${formalGbList}" class="chkBox checked"><input type="checkbox" name="multiFormalGb" th:value="${oneData.cd}" th:text="${'[' + oneData.cd + '] ' + oneData.cdNm}" checked="checked"/></label>
+							<label th:if="${formalGbList}" th:each="oneData, status : ${formalGbList}" class="chkBox checked"><input type="checkbox" name="multiFormalGb" th:value="${oneData.cd}" th:text="${oneData.cdNm}" checked="checked"/></label>
 						</td>
 					</tr>
 					<tr>
@@ -100,7 +100,7 @@
 						<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="itemkindTxt"></span>
+							<span id="itemkindCdTxt"></span>
 							<input type="hidden" name="itemkindCdList"/>
 						</td>
 					</tr>

+ 1 - 1
src/main/webapp/WEB-INF/views/statistics/HourlyTradingForm.html

@@ -75,7 +75,7 @@
 						<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="itemkindTxt"></span>
+							<span id="itemkindCdTxt"></span>
 							<input type="hidden" name="itemkindCdList"/>
 						</td>
 					</tr>

+ 250 - 0
src/main/webapp/WEB-INF/views/statistics/SubPaymentForm.html

@@ -0,0 +1,250 @@
+<!DOCTYPE html>
+<html lang="ko"
+	xmlns:th="http://www.thymeleaf.org">
+<!--
+ *******************************************************************************
+ * @source  : SubPaymentForm.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/payment/sub/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 style="width:25%;"/>
+						<col style="width:10%;"/>
+						<col style="width:20%;"/>
+					</colgroup>
+					<tr>
+						<th>기간<i class="required" title="필수" aria-hidden="true"></i></th>
+						<td colspan="5" id="terms">
+						</td>
+					</tr>
+					<tr>
+						<th>포인트 유형</th>
+						<td>
+							<select name="pointGb">
+								<option value="">[전체]</option>
+								<option th:if="${pointGbList}" th:each="oneData, status : ${pointGbList}" th:value="${oneData.cd}" th:text="${'[' + oneData.cd + '] ' + oneData.cdNm}"></option>
+							</select>
+						</td>
+						<th>상품권 유형</th>
+						<td colspan="3">
+							<select name="giftCardGb">
+								<option value="">[전체]</option>
+								<option th:if="${giftCardGbList}" th:each="oneData, status : ${giftCardGbList}" th:value="${oneData.cd}" th:text="${'[' + oneData.cd + '] ' + oneData.cdNm}"></option>
+							</select>
+						</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 class="left">
+					<button type="button" class="btn btn-default btn-lg" id="btnExcel">엑셀다운로드</button>
+				</li>
+				<li class="right">
+					<span class="btnGroup marR10">
+						<button type="button" class="btn btn-default btn-lg active" id="dayGbD" onclick="fnSetDayGb('D');">일별</button>
+						<button type="button" class="btn btn-default btn-lg" id="dayGbW" onclick="fnSetDayGb('W');">주별</button>
+						<button type="button" class="btn btn-default btn-lg" id="dayGbM" onclick="fnSetDayGb('M');">월별</button>
+					</span>
+				</li>
+			</ul>
+			<!-- //버튼 배치 영역 -->
+
+			<div id="gridList" style="width: 100%; height: 470px" class="ag-theme-balham"></div>
+		</div>
+		<!-- //리스트 영역 -->
+
+		<div class="panelStyle">
+			<table class="frmStyle" aria-describedby="잔액">
+				<colgroup>
+					<col style="width:30%;"/>
+					<col style="width:35%;"/>
+					<col style="width:35%;"/>
+				</colgroup>
+				<tr>
+					<th rowspan="2">현 잔액</th>
+					<th>포인트</th>
+					<th>상품권</th>
+				</tr>
+				<tr>
+					<td style="text-align: center;" th:text="${#numbers.formatInteger(remainPoint, 0,'COMMA')}"></td>
+					<td style="text-align: center;" th:text="${#numbers.formatInteger(remainGiftCard, 0,'COMMA')}"></td>
+				</tr>
+			</table>
+		</div>
+	</div>
+
+<script th:inline="javascript">
+/*<![CDATA[*/
+	let columnDefs = [
+		{ headerName: "기간", field: "day", width: 100, cellClass: 'text-center' },
+		{
+			headerName: "포인트", field: "", width: 600, cellClass: 'text-center',
+			children: [
+				{headerName: "적립액", field: "pntGive", width: 200, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "사용주문수", field: "pntOrdCnt", width: 200, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "사용액", field: "pntUse", width: 200, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				}
+			]
+		},
+		{
+			headerName: "상품권", field: "", width: 600, cellClass: 'text-center',
+			children: [
+				{headerName: "등록매수", field: "giftRegCnt", width: 200, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "사용주문수", field: "giftOrdCnt", width: 200, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				},
+				{headerName: "사용액", field: "giftUse", width: 200, cellClass: 'text-center',
+					cellRenderer: function(params) {
+						return gagaAgGrid.toAddComma(params.value);
+					}
+				}
+			]
+		}
+	];
+
+	let gridOptions = gagaAgGrid.getGridOptions(columnDefs);
+
+	gridOptions.autoGroupColumnDef = {
+			headerName: "일자",
+			field: "grouping",
+			width: 200,
+			cellRendererParams: {
+				suppressCount: true
+			}
+		};
+
+	// for expand everything
+	gridOptions.groupDefaultExpanded = -1;
+
+	// 검색
+	$('#btnSearch').on('click', function() {
+		// 입력 값 체크
+		if (!gagajf.validation($('#searchForm')))
+			return false;
+
+		gagaAgGrid.fetch($('#searchForm').prop('action'), gridOptions, '#searchForm', fnCreateTotal);
+	});
+
+	// 합계 생성
+	let fnCreateTotal = function() {
+		// Draw chart
+
+		let pntGive = 0;
+		let pntOrdCnt = 0;
+		let pntUse = 0;
+		let giftRegCnt = 0;
+		let giftOrdCnt = 0;
+		let giftUse = 0;
+
+		gridOptions.api.forEachNode(function(rowNode, index) {
+			if (!rowNode.group) {
+				if (typeof rowNode.data.pntGive == 'number') { pntGive += rowNode.data.pntGive; }
+				if (typeof rowNode.data.pntOrdCnt == 'number') { pntOrdCnt += rowNode.data.pntOrdCnt; }
+				if (typeof rowNode.data.pntUse == 'number') { pntUse += rowNode.data.pntUse; }
+				if (typeof rowNode.data.giftRegCnt == 'number') { giftRegCnt += rowNode.data.giftRegCnt; }
+				if (typeof rowNode.data.giftOrdCnt == 'number') { giftOrdCnt += rowNode.data.giftOrdCnt; }
+				if (typeof rowNode.data.giftUse == 'number') { giftUse += rowNode.data.giftUse; }
+			}
+		});
+
+		let data = {
+			day: 'TOTAL',
+			pntGive: pntGive, pntOrdCnt: pntOrdCnt, pntUse: pntUse,
+			giftRegCnt: giftRegCnt, giftOrdCnt: giftOrdCnt, giftUse: giftUse
+		};
+
+		gagaAgGrid.setPinnedRowData(gridOptions, data, 'top');
+	}
+
+	// 초기화 클릭시
+	$('#btnInit').on('click', function() {
+		$('#searchForm')[0].reset();
+
+		$('#cardIdTxt').html('');
+		$('#searchForm input[name=cardIdList]').val('');
+	});
+
+	// 엑셀다운로드
+	$('#btnExcel').on('click', function() {
+		gagaAgGrid.exportToExcel('부결제수단별통계 목록', gridOptions);
+	});
+
+	// 일자구분 변경 시
+	var fnSetDayGb = function(dayGb) {
+		$('#searchForm input[name=dayGb]').val(dayGb);
+		$('#dayGbD').removeClass('active');
+		$('#dayGbW').removeClass('active');
+		$('#dayGbM').removeClass('active');
+		$('#dayGb' + dayGb).addClass('active');
+		$('#btnSearch').trigger('click');
+	}
+
+	$(document).ready(function() {
+		cfnCreateCalendar('#terms', 'startDt', 'endDt', true, '주문', undefined, ['btnToday']);
+		$('.btnRecentWeek').trigger('click');
+
+		// Create a agGrid
+		gagaAgGrid.createGrid('gridList', gridOptions);
+
+	});
+/*]]>*/
+</script>
+
+</html>