moon há 5 anos atrás
pai
commit
90e4a50367

+ 88 - 0
src/main/java/com/style24/persistence/domain/WithdrawExc.java

@@ -0,0 +1,88 @@
+package com.style24.persistence.domain;
+
+import lombok.Data;
+
+import com.style24.persistence.TscBaseDomain;
+import com.style24.persistence.TscPageRequest;
+
+/**
+ * 회수예외 Domain
+ * 
+ * @author moon
+ * @since 2021. 03. 04
+ */
+@SuppressWarnings("serial")
+@Data
+public class WithdrawExc extends TscBaseDomain {
+
+	// 페이징 
+	private String pageingYn;
+	private int startRow;
+	private int endRow;
+	private TscPageRequest pageable;
+	private int pageNo = 1;
+	private int pageSize = 50;
+	private int pageUnit = 10;
+	
+	// 회수예외 
+	private String statusCd;           // 처리상태
+	private String dateCreated;        // 등록일자
+	private String customerName;       // 고객명
+	private Integer orderNo;           // 주문번호
+	private Integer orderDtlNo;        // 주문상세번호 
+	private String logisticsName;      // 택배사명
+	private String invoiceNo;          // 반송장번호
+	private String chargeType;         // 요금구분
+	private int chargeAmount;          // 배송비
+	private String userNameCreated;    // 작업자
+	private String reasonCd;           // 예외사유
+	private String brandNm;            // 브랜드명
+	private String productCode;        // 상품코드
+	private String skuCode;            // sku코드
+	private String productName;        // 상품명
+	private String skuValue;           // 속성
+	private String skuModelNo;         // 원코드
+	private int exceptionQty;          // 수량
+	private String siteCd;             // 주문경로
+	private Integer recallExceptionNo; // 반품예외처리번호 
+	private String recallStat;         // 반품대기처리상태 
+	private String goodsCd;            // 상품코드
+	private String adminMemo;          // WMS메시지
+	private int rnum;
+	private int rowspanCnt;            // rowspan 갯수 
+	private int rowspanRank;           // rowspan 순위 
+	private Integer recallExceptionItemNo;
+
+	
+	// 검색
+	
+	private String stDate;					// 조회 시작 기간
+	private String edDate;					// 조회 종료 기간
+	
+	
+	
+	private String searchType;				// 조회
+	private String searchText;				// 조회
+
+	private String dtlStDate;				// 상세조회 시작 기간
+	private String dtlEdDate;				// 상세조회 종료 기간
+	private String withdrawType;			// 회수상태
+	private String withdrawText;			//
+	private String delayDt;					// 회수지연일
+	private String delayDtType;				// 회수유형
+	private String goodsInfo;				// 상품정보(상품코드+사이즈코드)
+
+	private int seq;
+	private String goodsType;				// 상품유형
+	private int rfPntAmt;	//환원 포인트
+	private int rfPrePntAmt;	//취소 선포인트
+	private int rfGoodsCpnAmt;	//취소 상품쿠폰금액
+	private int rfCartCpnAmt;	//취소 장바구니쿠폰금액
+	private int rfPlusCpnAmt;	//취소 플러스쿠폰금액
+	private int rfSavePntAmt;
+	private int realOrdQty;
+	private int orgRealOrdAmt;
+	private int itemQty;	// 단품수량
+	private int itemPrice;	// 단품단가
+
+}

+ 127 - 0
src/main/java/com/style24/persistence/mybatis/shop/TsaWithdraw.xml

@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.style24.admin.biz.dao.TsaWithdrawDao">
+
+	<!-- 목록 페이징 정보 -->
+	<sql id="getListPagingCondition_sql">
+		<choose>
+		<when test="pageable != null">
+		    ) A
+		    JOIN ( SELECT @rownum := 0) R
+		)Z WHERE RNUM BETWEEN  #{pageable.startRow} AND #{pageable.endRow}
+		</when>
+		<otherwise>
+		    ) A
+		    JOIN ( SELECT @rownum := 0) R
+		)Z
+		</otherwise>
+		</choose>
+	</sql>
+	
+
+	<!-- 회수예외목록 건수 -->
+	<select id="getWithdrawExceptionListCount" parameterType="WithdrawExc" resultType="int">
+		/* TsaWithdraw.getWithdrawExceptionListCount */
+		SELECT COUNT(*) AS TOTCNT
+		  FROM (		
+				SELECT 
+					  A.RECALL_STAT   -- 반품대기처리상태
+					, A.STATUS_CD     -- 처리상태
+					, A.RECALL_EXCEPTION_NO -- 반품예외처리번호 
+				  FROM TB_ORDER_RECALL_EXCEPTION A 
+				  JOIN TB_ORDER_RECALL_EXCEPTION_ITEM B ON A.RECALL_EXCEPTION_NO = B.RECALL_EXCEPTION_NO
+				  WHERE B.REASON_CD NOT IN('확정 전 품절(재고없음)','확정 전 불량')
+					<if test='customerName != null and customerName != ""'>
+					AND   A.CUSTOMER_NAME = #{customerName}
+					</if>
+					<if test='orderNo != null and orderNo != ""'>
+					AND   A.ORDER_NO  = #{orderNo}
+					</if>
+					<if test='recallStat != null and recallStat != ""'>
+					AND   A.RECALL_STAT  = #{recallStat}
+					</if>
+					<if test='stDate != null and stDate != ""'>
+					AND   A.DATE_CREATED <![CDATA[>= ]]> STR_TO_DATE(REPLACE(#{stDate},'-',''), '%Y%m%d%H%i%s') 
+					</if>
+					<if test='edDate != null and edDate != ""'>
+					AND   A.DATE_CREATED <![CDATA[<]]> STR_TO_DATE(REPLACE(#{edDate},'-','') + 1 , '%Y%m%d%H%i%s') 
+					</if>
+			) A
+
+	</select>
+		
+	<!-- 회수예외목록 -->
+	<select id="getWithdrawExceptionList" parameterType="WithdrawExc" resultType="WithdrawExc">
+		/* TsaWithdraw.getWithdrawExceptionList */
+		SELECT Z.*
+			, ROW_NUMBER() OVER W AS ROWSPAN_CNT
+	        , ROW_NUMBER() OVER T AS ROWSPAN_RANK
+		FROM (
+		    SELECT A.*, @rownum := @rownum + 1  RNUM 
+		    FROM (
+				SELECT A.* 
+				  FROM (
+						SELECT 
+							  A.RECALL_STAT   -- 반품대기처리상태
+							, A.STATUS_CD     -- 처리상태
+							, A.DATE_CREATED  -- 등록일자
+							, A.CUSTOMER_NAME -- 고객명
+							, A.ORDER_NO      -- 주문번호
+							, B.ORDER_DTL_NO  -- 주문상세번호 
+							, A.LOGISTICS_NAME -- 택배사명
+							, A.INVOICE_NO     -- 반송장번호
+							, A.CHARGE_TYPE    -- 요금구분
+							, A.CHARGE_AMOUNT  -- 배송비
+							, A.USER_NAME_CREATED -- 작업자
+							, B.REASON_CD -- 예외사유
+							, IFNULL((SELECT GROUP_CONCAT(ADMIN_MEMO ORDER BY RECALL_EXCEPTION_MEMO_NO ) 
+							     FROM TB_ORDER_RECALL_EXCEPTION_MEMO C WHERE C.RECALL_EXCEPTION_NO = A.RECALL_EXCEPTION_NO  AND ADMIN_MEMO !='.'),'-') AS ADMIN_MEMO -- WMS메시지
+							, IFNULL((SELECT BRAND_KNM FROM TB_BRAND BR JOIN TB_GOODS GD ON BR.BRAND_CD = GD.BRAND_CD WHERE GD.GOODS_CD = C.GOODS_CD),'') AS BRAND_NM           -- 브랜드명
+							, B.PRODUCT_CODE   -- 상품코드
+							, B.SKU_CODE       -- SKU코드
+							, B.PRODUCT_NAME   -- 상품명
+							, B.SKU_VALUE      -- 속성
+							, C.SKU_MODEL_NO   -- 원코드
+							, B.EXCEPTION_QTY  -- 수량
+							, O.SITE_CD        -- 주문경로
+							, A.RECALL_EXCEPTION_NO -- 반품예외처리번호 
+							, IFNULL(C.GOODS_CD,'') AS GOODS_CD       -- 상품코드 
+							, B.RECALL_EXCEPTION_ITEM_NO 
+						  FROM TB_ORDER_RECALL_EXCEPTION A 
+						  JOIN TB_ORDER_RECALL_EXCEPTION_ITEM B ON A.RECALL_EXCEPTION_NO = B.RECALL_EXCEPTION_NO
+						  LEFT JOIN TB_ORDER O ON O.ORD_NO = A.ORDER_NO 
+						  LEFT JOIN TB_OPTION C ON C.OPT_CD = B.SKU_CODE
+						  WHERE B.REASON_CD NOT IN('확정 전 품절(재고없음)','확정 전 불량')
+							<if test='customerName != null and customerName != ""'>
+							AND   A.CUSTOMER_NAME = #{customerName}
+							</if>
+							<if test='orderNo != null and orderNo != ""'>
+							AND   A.ORDER_NO  = #{orderNo}
+							</if>
+							<if test='recallStat != null and recallStat != ""'>
+							AND   A.RECALL_STAT  = #{recallStat}
+							</if>
+							<if test='stDate != null and stDate != ""'>
+							AND   A.DATE_CREATED <![CDATA[>= ]]> STR_TO_DATE(REPLACE(#{stDate},'-',''), '%Y%m%d%H%i%s') 
+							</if>
+							<if test='edDate != null and edDate != ""'>
+							AND   A.DATE_CREATED <![CDATA[<]]> STR_TO_DATE(REPLACE(#{edDate},'-','')+ 1, '%Y%m%d%H%i%s')
+							</if>
+				) A
+				ORDER BY A.ORDER_NO, A.RECALL_EXCEPTION_NO, A.RECALL_EXCEPTION_ITEM_NO
+	<include refid="getListPagingCondition_sql"/>
+	      WINDOW W AS (PARTITION BY ORDER_NO ORDER BY ORDER_NO), T AS (PARTITION BY ORDER_NO ORDER BY ORDER_NO , RECALL_EXCEPTION_ITEM_NO DESC )
+	</select>
+
+
+	<!-- 회수예외 처리완료-->
+	<update id="updateWithdrawException" parameterType="WithdrawExc" >
+		/* TsaDelivery.deleteBangoods */
+		UPDATE TB_ORDER_RECALL_EXCEPTION SET
+		  RECALL_STAT = #{recallStat}
+		, RECALL_STAT_DT = NOW()
+		WHERE RECALL_EXCEPTION_NO = #{recallExceptionNo}
+
+	</update>
+
+</mapper>

+ 63 - 0
src/main/webapp/WEB-INF/views/delivery/DeliveryDetailItemForm.html

@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html lang="ko"
+	xmlns:th="http://www.thymeleaf.org">
+<!--
+ *******************************************************************************
+ * @source  : DeliveryDetailItemForm.html
+ * @desc    : 주문상세 단품 화면
+ *============================================================================
+ * STYLE24
+ * Copyright(C) 2021 TSIT, All rights reserved.
+ *============================================================================
+ * VER  DATE         AUTHOR      DESCRIPTION
+ * ===  ===========  ==========  =============================================
+ * 1.0  2021.03.05   moon       최초 작성
+ *******************************************************************************
+ -->
+
+
+<div class="modalPopup" data-width="650" >
+	<div class="panelStyle">
+		<div class="panelTitle">
+			<h2>세트구성 상품정보</h2>
+			<button type="button" class="close" onclick="uifnPopupClose('popupDeliveryDetailItemForm')"><i class="fa fa-times"></i></button>
+		</div>
+				
+		<div class="panelContent" style="overflow-y:auto;">
+			<form id="DeliveryDetailItemFrm">
+				<div id="gridDelvDetailItemInfo" style="width:100%; height: 260px;" class="ag-theme-balham"></div>
+			</form>
+		</div>
+	</div>
+</div>
+
+<script th:inline="javascript">
+/*<![CDATA[*/
+
+var delvDetailItemList = [[${delvDetailItemList}]];
+
+	// specify the columns
+	var columnDefsDelvDetailItemInfo = [
+			{headerName: "상품코드",	field: "itemCd", 	width: 130, cellClass: 'text-center'},
+			{headerName: "상품명", 	field: "goodsNm", 	width: 200, cellClass: 'text-left'},
+			{headerName: "색상",  	field: "optCd1", 	width: 80, cellClass: 'text-center'},
+			{headerName: "사이즈", 	field: "optCd2", 	width: 80, cellClass: 'text-center'},
+			{headerName: "수량",  	field: "itemQty", 	width: 50, cellClass: 'text-center'},
+			{headerName: "단가", 		field: "itemPrice", width: 60, cellClass: 'text-right',
+				cellRenderer: function (params) {
+					return params.value.addComma();
+				}
+			},
+	];
+
+	$(document).ready(function() {
+		// Get GridOptions
+		var gridDelvDetailItemInfo = gagaAgGrid.getGridOptions(columnDefsDelvDetailItemInfo);
+		gagaAgGrid.createGrid('gridDelvDetailItemInfo', gridDelvDetailItemInfo);
+		gridDelvDetailItemInfo.api.setRowData(delvDetailItemList);
+		$('.ag-status-bar').hide();
+	});
+/*]]>*/
+</script>
+
+</html>

+ 308 - 0
src/main/webapp/WEB-INF/views/delivery/DeliveryExceptionListForm.html

@@ -0,0 +1,308 @@
+<!DOCTYPE html>
+<html lang="ko"
+	xmlns:th="http://www.thymeleaf.org">
+<!--
+ *******************************************************************************
+ * @source  : DeliveryExceptionListForm.html
+ * @desc    : 출고예외관리 Page
+ *=============================================================
+ * ISTYLE24
+ * Copyright(C) 2021 TSIT, All rights reserved.
+ *=============================================================
+ * VER  DATE         AUTHOR      DESCRIPTION
+ * ===  ===========  ==========  ==================================
+ * 1.0  2021.02.19   moon        최초 작성
+ * 1.1  
+ ********************************************************************************
+ -->
+	<div id="main">
+		<!-- 메인타이틀 영역 -->
+		<div class="main-title">
+		</div>
+		<!-- //메인타이틀 영역 -->
+		<!-- 메뉴 설명 -->
+		<div class="infoBox menu-desc">
+		</div>
+		<!-- //메뉴 설명 -->
+		<!-- 검색조건 영역 -->
+		<div class="panelStyle">
+			<!-- TITLE -->
+			<div class="panelTitle">
+				<h3><i class="fa fa-info-circle"></i>아래 검색조건 중 <font color="red">등록일</font>은 꼭 입력해 주세요.</h3>
+				<span class="panelControl">
+					<i class="fa fa-chevron-up"></i>
+				</span>
+			</div>
+			<!-- //TITLE -->
+			<div class="panelContent">	
+				<form id="searchForm" name="searchForm" action="#" th:action="@{'/delivery/deliveryExcpt/list'}" onsubmit="fnSearchList(); return false;">
+					<table class="frmStyle">
+						<colgroup>
+							<col style="width:8%;"/>
+							<col style="width:12%;"/>
+							<col style="width:8%;"/>
+							<col style="width:12%;"/>
+							<col style="width:8%;"/>
+							<col style="width:12%;"/>
+						</colgroup>
+						<tr>
+							<th class="dashR">주문자명</th>
+							<td class="dashR">
+								<input type="text" class="w40p" name="orderNm" placeholder="" maxlength="20" />
+							</td>
+							<th class="dashR">주문번호</th>
+							<td class="dashR">
+								<input type="text" class="w40p" name="orderNo" placeholder="" maxlength="20" data-valid-type="numeric"/>
+							</td>
+							<th class="dashR">처리상태</th>
+							<td class="dashR">
+								<select name="delYn" id="delYn">
+									<option value="">전체</option>
+									<option value="대기" selected>대기</option>
+									<option value="처리완료">처리완료</option>
+								</select>
+							</td>
+						</tr>
+						<tr>
+							<th class="dashR">등록일</th>
+							<td colspan="4" class="dashR">
+								<span id="terms"></span>
+							</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" onclick="$('#searchForm')[0].reset(); fnInitCalendar();">초기화</button>
+						<button type="button" id="btnExcel" class="btn btn-info btn-lg" >엑셀다운로드</button>
+						</li>
+					</ul>
+				</form>
+				</div>
+		</div>
+		<!-- //검색조건 영역 -->
+
+		<!-- 리스트 영역 -->
+		<div class="panelStyle">
+			<!--  
+			<ul class=panelBar>
+				<li class="left">
+					<button type="button" id="btnSoldout" class="btn btn-danger btn-lg" onclick="deleteBangoods();" >삭제</button>
+				</li>
+				<li class="right">
+					<button type="button" id="btnSave" class="btn btn-success btn-lg btnRight" onclick="registerBangoods();">등록</button>
+				</li>
+			</ul>
+			 -->
+			<div class="panelContent" style="overflow: hidden;">
+				<div id="gridList" style="width:100%; height: 500px;" class="ag-theme-balham"></div>
+			</div>
+		</div>
+		<!-- //리스트 영역 -->
+	</div>
+
+<script th:inline="javascript">
+/*<![CDATA[*/
+	
+	/*************************************************************************
+	* AG-GRID 영역 
+	**************************************************************************/
+	
+	var uploadGoodsUrl = [[${@environment.getProperty('upload.goods.view')}]]; 
+	var roleCd = [[${sessionInfo.roleCd}]]; 
+
+	var columnDefs = [
+		/*
+		{ width: 42, minWidth: 42, cellClass: 'text-center', headerCheckboxSelection: true, headerCheckboxSelectionFilteredOnly: true
+			, checkboxSelection: function (params) {
+				return  (params.data.delYn == 'N' ) ? true : false;
+			}	
+		},
+		*/
+		{headerName: "반품예외처리번호",			field: "delvBanGoodsSq",width: 50,	cellClass: 'text-center', hide: true},
+		{headerName: "처리상태",				field: "delYn",			width: 150,	cellClass: 'text-center'},
+		{headerName: "등록일자",				field: "brandKnm",		width: 150,	cellClass: 'text-center'},
+		{headerName: "주문번호",				field: "delvLocNm",		width: 150,	cellClass: 'text-center'},
+		
+		{headerName: "주문자명",				field: "delvLocNm",		width: 150,	cellClass: 'text-center'},
+		{headerName: "택배사명",				field: "delvLocNm",		width: 150,	cellClass: 'text-center'},
+		{headerName: "반송장번호",				field: "delvLocNm",		width: 150,	cellClass: 'text-center'},
+		{headerName: "요금구분",				field: "delvLocNm",		width: 150,	cellClass: 'text-center'},
+		{headerName: "배송비",				field: "delvLocNm",		width: 150,	cellClass: 'text-center'},
+		{headerName: "작업자",				field: "delvLocNm",		width: 150,	cellClass: 'text-center'},
+		{headerName: "예외사유",				field: "delvLocNm",		width: 150,	cellClass: 'text-center'},
+		{headerName: "WMS메시지",				field: "delvLocNm",		width: 150,	cellClass: 'text-center'},
+		{headerName: "브랜드명",				field: "delvLocNm",		width: 150,	cellClass: 'text-center'},
+		{headerName: "상품코드",				field: "delvLocNm",		width: 150,	cellClass: 'text-center'},
+		{headerName: "SKU코드",				field: "delvLocNm",		width: 150,	cellClass: 'text-center'},
+		
+		
+		
+		{headerName: "상품명",				field: "goodsNm",		width: 150,	cellClass: 'text-center'},
+		{
+			headerName: "상품코드", field: "goodsCd", width: 130, cellClass: 'text-center', sortable: true,
+			cellRenderer: function (params) {
+				
+				if (roleCd.indexOf("C") < 0) {
+					return "<a href=\"javascript:void(0);\" onclick=\"cfnOpenGoodsDetailPopup('U','" + params.value + "');\">" + params.value + "</a>";
+				} else {
+					return params.value;
+				}
+			}
+		},
+		{headerName: "속성",		    field: "colorCd",		width: 80,	cellClass: 'text-center'},
+		{headerName: "원코드",		field: "sizeCd",		width: 80,	cellClass: 'text-center'},
+		{headerName: "수량",		field: "goodsStat",		width: 80,	cellClass: 'text-center'},
+		{headerName: "주문경로",	field: "delvBanStdt",	width: 150,	cellClass: 'text-center'}
+		
+	];
+
+	var gridOptions = gagaAgGrid.getGridOptions(columnDefs);
+	gridOptions.rowSelection = 'multiple';
+	
+	//gridOptions.rowHeight = 60;
+	/*************************************************************************
+	*  조회 버튼 클릭 시
+	**************************************************************************/
+	$('#btnSearch').on('click', function() {
+		fnSearchList();
+	});
+
+	/*************************************************************************
+	*  조회 
+	**************************************************************************/
+	var fnSearchList = function() {
+		if($('#stDate').val() == ''){
+			mcxDialog.alert('시작 기간을 입력하세요.');
+			return;
+		}
+
+		if($('#edDate').val() == ''){
+			mcxDialog.alert('종료 기간을 입력하세요.');
+			return;
+		}
+
+		// 날짜 유효성 체크
+		if (Number($('#stDate').val().replaceAll("-", "")) > Number($('#edDate').val().replaceAll("-", ""))) {
+			mcxDialog.alert("시작일은 종료일보다 클 수 없습니다.");
+			return;
+		}
+
+		gagaAgGrid.fetch($('#searchForm').prop('action'), gridOptions, '#searchForm', function() {
+		});
+	}
+
+	/*************************************************************************
+	*  달력 초기화 
+	**************************************************************************/		
+	var fnInitCalendar = function() {
+		cfnChangeCalendar('1d', $('#stDate'), $('#edDate')); //달력 초기화
+	}
+
+	/*************************************************************************
+	*  업체 콤보박스 변경 시
+	**************************************************************************/	
+	$('#searchForm select[name=supplyCompCd]').on('change', function() {
+		var actionUrl = '/renderer/supplyCompany/brand/list/'+ $(this).val();
+		cfnCreateCombo(actionUrl, $('#searchForm select[name=brandCd]'), "[전체]");
+	});
+
+	/*************************************************************************
+	*  엑셀다운로드
+	**************************************************************************/		
+	$('#btnExcel').on('click', 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.excelStyles = [
+			{
+				id: 'dateFormat',
+
+				dataType: 'dateTime',
+				numberFormat: {
+					format: 'YYYY-MM-DD;@'
+				}
+			},
+			{
+				id: 'textFormat',
+				dataType: 'string'
+			}
+		]
+
+		gridOptions.api.exportDataAsExcel(params);
+	});
+
+	/*************************************************************************
+	*  삭제
+	**************************************************************************/	
+	var deleteBangoods = function(){
+		
+		var selectedData = gridOptions.api.getSelectedNodes();
+		
+		$.each(selectedData, function(idx, row) {
+	
+	 		if(row.data.delYn == "Y") {
+	 			gridOptions.api.deselectIndex(row.rowIndex);
+	 		}
+	 	});
+		
+		
+		mcxDialog.confirm("삭제하시겠습니까?", {
+		    cancelBtnText: "취소",
+		    sureBtnText: "확인",
+		    sureBtnClick: function() {
+
+	            var gridData = gagaAgGrid.removeRowData(gridOptions,false);
+
+	            if (gridData.length == 0) {
+	            	mcxDialog.alert('선택된 행이 없습니다.');
+	                return;
+	            }
+
+	            var createData = [];
+	            $.each(gridData, function(idx, item) {
+	                var param = new Object;
+
+	                param.delvBanGoodsSq = item.delvBanGoodsSq;
+	                param.goodsCd = item.goodsCd;
+	                param.colorCd = item.colorCd;
+	                param.sizeCd = item.sizeCd;
+
+	                createData.push(param);
+	            });
+
+	            var jsonData = JSON.stringify(createData);
+	            gagajf.ajaxJsonSubmit('/delivery/bangoods/delete', jsonData, fnSearchList);
+	        }
+		});
+	}
+
+	/*************************************************************************
+	*  등록 팝업 호출 
+	**************************************************************************/	
+	var registerBangoods = function(){
+		var actionUrl = "/delivery/bangoods/regist/form";
+		cfnOpenModalPopup(actionUrl,'popupRegistBangoods');
+	}
+
+	$(document).ready(function() {
+		gagaAgGrid.createGrid('gridList', gridOptions);
+		cfnCreateCalendar('#terms', 'stDate', 'edDate', true, '출고금지상품관리');
+		//var hideList = ["btnThisWeek", "btnYesterWeek", "btnRecentMonth", "btnThisMonth", "btnYesterMonth", "btnRecent3Month"];
+		//cfnCreateCalendar('#terms', 'stDate', 'edDate', true, '출고금지상품관리', '', hideList);
+		fnInitCalendar();
+	});
+
+/*]]>*/
+</script>
+</html>

+ 109 - 0
src/main/webapp/WEB-INF/views/delivery/SaveInvoiceForm.html

@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<html lang="ko"
+	xmlns:th="http://www.thymeleaf.org">
+<!--
+ *******************************************************************************
+ * @source  : SaveInvoiceForm.html
+ * @desc    : 송장등록/수정 화면
+ *============================================================================
+ * STYLE24
+ * Copyright(C) 2021 TSIT, All rights reserved.
+ *============================================================================
+ * VER  DATE         AUTHOR      DESCRIPTION
+ * ===  ===========  ==========  =============================================
+ * 1.0  2021.03.06   moon       최초 작성
+ *******************************************************************************
+ -->
+
+
+<div class="modalPopup" data-width="900" >
+	<div class="panelStyle">
+		<div class="panelTitle">
+			<h2>배송정보</h2>
+			<button type="button" class="close" onclick="uifnPopupClose('popupChangeInvoice')"><i class="fa fa-times"></i></button>
+		</div>
+		<div class="panelContent" style="overflow-y:auto;">
+		<form id="saveInvoiceForm">
+			<table class="frmStyle">
+				<colgroup>
+					<col style="width:160px;" />
+					<col />
+					<col />
+					<col />
+					<col />
+					<col />
+					<col />
+				</colgroup>
+				<tbody>
+				<tr>
+					<th>배송업체</th>
+					<th:block th:if="${shipCompanyList}">
+						<td>
+							<select name="shipCompany">
+								<option value="">[선택하세요]</option>
+								<option th:if="${shipCompanyList}" th:each="oneData, status : ${shipCompanyList}" th:value="${oneData.cd}" th:text="${oneData.cdNm}" th:selected="${oneData.cd == ordDelivery.shipCompCd}"></option>
+							</select>
+						</td>
+						<th>송장번호</th>
+						<td><input type="text" name="invoiceNo" th:value="${#strings.defaultString(ordDelivery.invoiceNo,'')}" data-valid-type="numeric" ></td>
+					</th:block>
+					<td>
+						<button type="button" class="btn btn-success" id="saveAccountBtn" onclick="fnSaveAccount();">저장</button>
+					</td>
+				</tbody>
+			</table>
+		</form>
+		</div>
+	</div>
+</div>
+
+
+<script th:inline="javascript">
+/*<![CDATA[*/
+/* 이벤트 바인딩 관련 */
+	var ordDtlNo = [[${ordDelivery.ordDtlNo}]];
+	var ordDtlStat = [[${ordDelivery.ordDtlStat}]];
+
+	/* 환불계좌번호 저장 */
+	var fnSaveAccount = function(){
+		var shipCompCd = $("#saveInvoiceForm select[name=shipCompany]").val();
+		var invoiceNo = $("#saveInvoiceForm input[name=invoiceNo]").val();
+
+
+		if(gagajf.isNull(shipCompCd)) {
+			mcxDialog.alert('택배사 선택을 해주세요.');
+			return;
+		}
+
+		if(gagajf.isNull(invoiceNo)) {
+			mcxDialog.alert('송장번호를 입력해 주세요.');
+			return;
+		}
+
+
+		mcxDialog.confirm('송장등록/수정된 내용은 물류시스템에 전송되지 않습니다. <br> 저장 하시겠습니까?', {
+			cancelBtnText: "취소",
+			sureBtnText: "확인",
+			sureBtnClick: function () {
+					var param = {};
+					param.shipCompCd = shipCompCd;
+					param.invoiceNo  = invoiceNo;
+					param.ordDtlNo   = ordDtlNo;
+
+				var jsonData = JSON.stringify([param]);
+				gagajf.ajaxJsonSubmit('/delivery/orderDetail/save', jsonData, function (result) {
+					uifnPopupClose('popupChangeInvoice');
+				});
+			}
+		});
+	};
+
+	$(document).ready(function() {
+
+
+	});
+
+/*]]>*/
+</script>
+
+</html>

+ 330 - 0
src/main/webapp/WEB-INF/views/withdraw/WithdrawExceptionListForm.html

@@ -0,0 +1,330 @@
+<!DOCTYPE html>
+<html lang="ko"
+	xmlns:th="http://www.thymeleaf.org">
+<!--
+ *******************************************************************************
+ * @source  : WithdrawExceptionListForm.html
+ * @desc    : 회수예외관리 Page
+ *=============================================================
+ * ISTYLE24
+ * Copyright(C) 2021 TSIT, All rights reserved.
+ *=============================================================
+ * VER  DATE         AUTHOR      DESCRIPTION
+ * ===  ===========  ==========  ==================================
+ * 1.0  2021.02.22   moon        최초 작성
+ * 1.1  
+ ********************************************************************************
+ -->
+ 
+	<div id="main">
+		<!-- 메인타이틀 영역 -->
+		<div class="main-title">
+		</div>
+		<!-- //메인타이틀 영역 -->
+		<!-- 메뉴 설명 -->
+		<div class="infoBox menu-desc">
+		</div>
+		<!-- //메뉴 설명 -->
+		
+		<!-- 검색조건 영역 -->
+		<form id="searchForm" name="searchForm" action="#" th:action="@{'/withdraw/exception/list'}" onsubmit="fnSearchList(); return false;">
+		<div class="panelStyle">
+			<!-- TITLE -->
+			<div class="panelTitle">
+				<h3><i class="fa fa-info-circle"></i>아래 검색조건 중 <font color="red">등록일</font>은 꼭 입력해 주세요.</h3>
+				<span class="panelControl">
+					<i class="fa fa-chevron-up"></i>
+				</span>
+			</div>
+			<!-- //TITLE -->
+			<div class="panelContent">	
+				
+					<table class="frmStyle">
+						<colgroup>
+							<col style="width:8%;"/>
+							<col style="width:12%;"/>
+							<col style="width:8%;"/>
+							<col style="width:12%;"/>
+							<col style="width:8%;"/>
+							<col style="width:12%;"/>
+						</colgroup>
+						<tr>
+							<th class="dashR">주문자명</th>
+							<td class="dashR">
+								<input type="text" class="w40p" name="customerName" placeholder="" maxlength="20" />
+							</td>
+							<th class="dashR">주문번호</th>
+							<td class="dashR">
+								<input type="text" class="w40p" name="orderNo" placeholder="" maxlength="20" data-valid-type="numeric"/>
+							</td>
+							<th class="dashR">처리상태</th>
+							<td class="dashR">
+								<select name="recallStat" id="recallStat">
+									<option value="">전체</option>
+									<option value="P" selected>대기</option>
+									<option value="S">처리완료</option>
+								</select>
+							</td>
+						</tr>
+						<tr>
+							<th class="dashR">등록일</th>
+							<td colspan="4" class="dashR">
+								<span id="terms"></span>
+							</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" onclick="$('#searchForm')[0].reset(); fnInitCalendar();">초기화</button>
+						<button type="button" id="btnExcel" class="btn btn-info btn-lg" >엑셀다운로드</button>
+						</li>
+					</ul>
+
+				</div>
+		</div>
+		<!-- //검색조건 영역 -->
+
+		<!-- 리스트 영역 -->
+		<div class="panelStyle">
+			<ul class="panelBar">
+				<li class="right">
+					검색결과 : <strong><span id="gridRowTotalCount">0</span> 건</strong>&nbsp;
+					쪽번호 <span id="pgNo">0</span>/ <strong id="endPgNo">0</strong>&nbsp;&nbsp;
+					<select id="pageSize" name="pageSize">
+						<option value="20" selected="selected">20개씩 보기</option>
+						<option value="50">50개씩 보기</option>
+						<option value="100">100개씩 보기</option>
+						<option value="500">500개씩 보기</option>
+						<option value="1000">1000개씩 보기</option>
+					</select>
+					<input type="hidden" name="pageNo" id="pageNo" value ="1"/>
+				</li>
+			</ul>
+			<div id="gridList" style="width:100%; height: 700px;" class="ag-theme-balham"></div>
+			<ul class="panelBar">
+				<li class="center">
+					<div class="tablePaging" id="withdrawExceptionListPagination"></div>
+				</li>
+			</ul>
+					 
+		</div>
+		</form>
+		<!-- //리스트 영역 -->
+	</div>
+<script type="text/javascript" src="/ux/plugins/gaga/gaga.paging.js?v=20210114"></script>
+<script th:inline="javascript">
+/*<![CDATA[*/
+	
+	/*************************************************************************
+	* AG-GRID 영역 
+	**************************************************************************/
+	var uploadGoodsUrl = [[${@environment.getProperty('upload.goods.view')}]]; 
+	var roleCd = [[${sessionInfo.roleCd}]]; 
+
+	var columnDefs = [
+		{headerName: "반품예외처리번호",		field: "recallExceptionNo", width: 50,	cellClass: 'text-center', hide: true},
+		{headerName: "No.",				field: "rnum",				width: 50,	cellClass: 'text-center'},
+		{headerName: "처리상태",			field: "recallStat",		width: 100,	cellClass: 'text-center',rowSpan: params => params.data.rowspanRank === 1 ? params.data.rowspanCnt : 1,
+		    cellClassRules: {
+		        'cell-span': "data.rowspanRank == 1"
+		      },
+			cellRenderer: function(params) {
+				var btnText = '';
+				if(params.data.recallStat === 'P') {
+					btnText= '<a href="javascript:void(0);"  onclick="fnComplete(\''+params.data.recallExceptionNo+'\')" class="btn btn-success btn-ssm">대기</a>';
+				} else { btnText = '완료' }
+				return btnText;
+			}			
+		},
+		
+		{headerName: "주문번호",			field: "orderNo",			width: 200,	cellClass: 'text-center', rowSpan: params => params.data.rowspanRank === 1 ? params.data.rowspanCnt : 1,  
+		    cellClassRules: {
+		        'cell-span': "data.rowspanRank == 1"
+		      },
+			
+			cellRenderer: function (params) {
+			if (roleCd.indexOf("C") < 0) {
+				return "<a href=\"javascript:void(0);\" onclick=\"cfnOpenOrderDetailPopup('" + params.data.orderNo + "');\">" + params.data.orderNo + "</a>";
+			} else {
+				return params.value;
+			}
+			}
+	
+		},
+		{headerName: "주문자명",			field: "customerName",		width: 100,	cellClass: 'text-center'},
+		{headerName: "택배사명",			field: "logisticsName",		width: 100,	cellClass: 'text-center'},
+		{headerName: "반송장번호",			field: "invoiceNo",			width: 120,	cellClass: 'text-center'},
+		{headerName: "요금구분",			field: "chargeType",		width: 80,	cellClass: 'text-center'},
+		{headerName: "배송비",			field: "chargeAmount",		width: 100,	cellClass: 'text-right'
+			,valueFormatter: function(params) {
+				if (params.value > 0) {
+					return params.value.addComma();
+				}else{
+					return '0';
+				}
+			}
+		},
+		{headerName: "작업자",			field: "userNameCreated",	width: 100,	cellClass: 'text-center'},
+		{headerName: "예외사유",			field: "reasonCd",			width: 150,	cellClass: 'text-center'},
+		{headerName: "WMS메시지",			field: "adminMemo",			width: 300,	cellClass: 'text-left'},
+		{headerName: "브랜드명",			field: "brandNm",			width: 150,	cellClass: 'text-center'},
+		{headerName: "상품코드",			field: "productCode",		width: 100,	cellClass: 'text-center',
+			cellRenderer: function (params) {
+				if (roleCd.indexOf("C") < 0) {
+					return "<a href=\"javascript:void(0);\" onclick=\"cfnOpenGoodsDetailPopup('U','" + params.data.goodsCd + "');\">" + params.value + "</a>";
+				} else {
+					return params.value;
+				}
+			}				
+		},
+		{headerName: "SKU코드",			field: "skuCode",			width: 100,	cellClass: 'text-center'},
+		{headerName: "상품명",			field: "productName",		width: 200,	cellClass: 'text-left'},
+		{headerName: "속성",		    	field: "skuValue",			width: 80,	cellClass: 'text-center'},
+		{headerName: "원코드",			field: "skuModelNo",		width: 150,	cellClass: 'text-left'},
+		{headerName: "수량",				field: "exceptionQty",		width: 80,	cellClass: 'text-right'},
+		{headerName: "주문경로",			field: "siteCd",			width: 100,	cellClass: 'text-left'},
+		{headerName: "등록일시",			field: "dateCreated",		width: 150,	cellClass: 'text-center'}
+		
+	];
+
+	var gridOptions = gagaAgGrid.getGridOptions(columnDefs);
+	gridOptions.suppressRowTransform =true;
+	//gridOptions.rowSelection = 'multiple';
+	
+	gridOptions.rowHeight = 35;
+	/*************************************************************************
+	*  조회 버튼 클릭 시
+	**************************************************************************/
+	$('#btnSearch').on('click', function() {
+		fnSearchList();
+	});
+
+	/*************************************************************************
+	*  조회 
+	**************************************************************************/
+	var fnSearchList = function() {
+		if($('#stDate').val() == ''){
+			mcxDialog.alert('시작 기간을 입력하세요.');
+			return;
+		}
+
+		if($('#edDate').val() == ''){
+			mcxDialog.alert('종료 기간을 입력하세요.');
+			return;
+		}
+
+		// 날짜 유효성 체크
+		if (Number($('#stDate').val().replaceAll("-", "")) > Number($('#edDate').val().replaceAll("-", ""))) {
+			mcxDialog.alert("시작일은 종료일보다 클 수 없습니다.");
+			return;
+		}
+
+		gagaPaging.init('searchForm', fnSearchCallBack, 'withdrawExceptionListPagination', $('#searchForm').find('#pageSize').val());
+	    gagaPaging.load($("#searchForm input[name=pageNo]").val());
+	}
+	
+	/*************************************************************************
+	*  조회 콜백
+	**************************************************************************/
+	var fnSearchCallBack = function(result){
+
+		$('#searchForm').find('#gridRowTotalCount').html(result.pageing.pageable.totalCount.addComma());
+		$('#searchForm').find('#pageNo').val(result.pageing.pageable.pageNo.addComma());
+		$('#searchForm').find('#pgNo').html(result.pageing.pageable.pageNo.addComma());
+		$('#searchForm').find('#endPgNo').html(result.pageing.pageable.totalPage.addComma());
+		gridOptions.api.setRowData(result.withdrawExceptionList);
+		gagaPaging.createPagination(result.pageing.pageable);
+		
+	}
+	
+	/*************************************************************************
+	*  달력 초기화 
+	**************************************************************************/		
+	var fnInitCalendar = function() {
+		cfnChangeCalendar('7d', $('#stDate'), $('#edDate')); //달력 초기화
+	}
+
+	
+	function fnRowSpan(params) {
+		alert("alert");  
+		var orderNo = params.data.orderNo;
+		  alert("orderNo: "+orderNo);
+		  if (orderNo == 18691602) {
+		    // have all Russia age columns width 2
+		    return 2;
+		  } else {
+		    // all other rows should be just normal
+		    return 1;
+		  }
+		}
+	// rowSpan: params => params.data.orderNo === '18692992' ? 2 : 1	
+	
+	/*************************************************************************
+	*  회수예외 처리완료 버튼 - 대기->완료  업데이트
+	**************************************************************************/	
+	var fnComplete = function(recallExceptionNo) {
+		var params = {};
+		params.recallExceptionNo = recallExceptionNo;
+		mcxDialog.confirm('처리완료 하시겠습니까?', {
+			cancelBtnText: "취소",
+			sureBtnText: "확인",
+			sureBtnClick: function(){
+				var jsonData = JSON.stringify(params);
+				gagajf.ajaxJsonSubmit('/withdraw/exception/complete', jsonData, fnCompleteCallback);
+			}
+		});
+	};
+	
+	/*************************************************************************
+	*  회수예외 처리완료 콜백
+	**************************************************************************/		
+	var fnCompleteCallback = function() {
+		fnSearchList();
+	};
+	
+
+	/*************************************************************************
+	*  엑셀다운로드
+	**************************************************************************/		
+	$('#btnExcel').on('click', function() {
+		var totalRows = gridOptions.api.getDisplayedRowCount();
+		if(totalRows==0){
+			mcxDialog.alert('조회된 내역이 없습니다.');
+			return;
+		}
+
+		var date = new Date().format("YYYYMMDDHHmmss");
+		var params = {
+			fileName : "WMS회수예외목록_"+ date,
+			sheetName: "DATA"
+		}
+		gridOptions.excelStyles = [
+			{
+				id: 'dateFormat',
+				dataType: 'dateTime',
+				numberFormat: {
+					format: 'YYYY-MM-DD;@'
+				}
+			},
+			{
+				id: 'textFormat',
+				dataType: 'string'
+			}
+		]
+		gridOptions.api.exportDataAsExcel(params);
+	});
+
+	/*************************************************************************
+	*  init
+	**************************************************************************/		
+	$(document).ready(function() {
+		gagaAgGrid.createGrid('gridList', gridOptions);
+		cfnCreateCalendar('#terms', 'stDate', 'edDate', true, '');
+		fnInitCalendar();
+	});
+
+/*]]>*/
+</script>
+</html>