견문목록 일괄결재 기능 추가.
parent
dc091550bc
commit
c2da2f1b47
|
|
@ -14,6 +14,7 @@ import org.springframework.web.servlet.ModelAndView;
|
|||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -96,6 +97,7 @@ public class AffairController { // 첩보수집활동 > 외사경찰 견문관
|
|||
break;
|
||||
}
|
||||
}
|
||||
mav.addObject("userOrgan", loginUser.getOgCd());
|
||||
mav.addObject("accessAuth", accessAuth);
|
||||
mav.addObject("apprvAuth", apprvAuth);
|
||||
affairBoard.setQueryInfo();
|
||||
|
|
@ -188,6 +190,7 @@ public class AffairController { // 첩보수집활동 > 외사경찰 견문관
|
|||
}
|
||||
mav.addObject("affair", affairBoard);
|
||||
mav.addObject("userSeq",loginUser.getUserSeq());
|
||||
mav.addObject("userOrgan", loginUser.getOgCd());
|
||||
//메뉴권한 확인
|
||||
mav.addObject("accessAuth", authMgtService.selectAccessConfigList(loginUser.getUserSeq(), "/affair/affairMgt").get(0).getAccessAuth());
|
||||
String apprvAuth = authMgtService.selectApprovalConfigList(loginUser.getUserSeq(), "/affair/affairMgt").get(0).getApprovalAuth();
|
||||
|
|
@ -207,7 +210,8 @@ public class AffairController { // 첩보수집활동 > 외사경찰 견문관
|
|||
}
|
||||
|
||||
@PostMapping("/affairStateChange")
|
||||
public Integer affairStateChange(@AuthenticationPrincipal UserInfo loginUser, AffairRating rating){
|
||||
return affairService.affairStateChange(loginUser, rating);
|
||||
@ResponseBody
|
||||
public Integer affairStateChange(@AuthenticationPrincipal UserInfo loginUser, @RequestBody List<AffairRating> ratingList){
|
||||
return affairService.affairStateChange(loginUser, ratingList);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,36 +119,38 @@ public class AffairService extends BaseService { // 견문보고
|
|||
}
|
||||
|
||||
@Transactional
|
||||
public Integer affairStateChange(UserInfo loginUser, AffairRating rating) {
|
||||
AffairRating savedRating = affairRatingRepository.findById(new AffairRating.AffairRatingId(rating.getAffairKey(), rating.getRatingOrgan())).orElse(null);
|
||||
if(savedRating != null){
|
||||
if(rating.getHeadApprv() == null){
|
||||
savedRating.setSectionNm(loginUser.getUserNm());
|
||||
savedRating.setSectionApprvDt(LocalDateTime.now());
|
||||
savedRating.setSectionApprv(rating.getSectionApprv());
|
||||
savedRating.setSectionEtc(rating.getSectionEtc());
|
||||
savedRating.setAffairStatus(rating.getSectionApprv());
|
||||
}else{
|
||||
savedRating.setHeadNm(loginUser.getUserNm());
|
||||
savedRating.setHeadApprvDt(LocalDateTime.now());
|
||||
savedRating.setHeadApprv(rating.getHeadApprv());
|
||||
savedRating.setHeadEtc(rating.getHeadEtc());
|
||||
savedRating.setAffairRate(rating.getAffairRate());
|
||||
savedRating.setOrganUp(rating.getOrganUp()==null?"F":rating.getOrganUp());
|
||||
savedRating.setAffairStatus(rating.getHeadApprv());
|
||||
if(savedRating.getOrganUp().equals("T")){
|
||||
List<String> organList = loginUser.getUpOrganCdList();
|
||||
String upOrgan = organList.get(organList.indexOf(savedRating.getRatingOrgan())-1);
|
||||
AffairRating upRating = new AffairRating();
|
||||
upRating.setRatingOrgan(upOrgan);
|
||||
upRating.setAffairKey(savedRating.getAffairKey());
|
||||
upRating.setAffairStatus("DST002");
|
||||
affairRatingRepository.save(upRating);
|
||||
public Integer affairStateChange(UserInfo loginUser, List<AffairRating> ratingList) {
|
||||
for(AffairRating rating : ratingList){
|
||||
AffairRating savedRating = affairRatingRepository.findById(new AffairRating.AffairRatingId(rating.getAffairKey(), loginUser.getOgCd())).orElse(null);
|
||||
if(savedRating != null){
|
||||
if(rating.getHeadApprv() == null){
|
||||
savedRating.setSectionNm(loginUser.getUserNm());
|
||||
savedRating.setSectionApprvDt(LocalDateTime.now());
|
||||
savedRating.setSectionApprv(rating.getSectionApprv());
|
||||
savedRating.setSectionEtc(rating.getSectionEtc());
|
||||
savedRating.setAffairStatus(rating.getSectionApprv());
|
||||
}else{
|
||||
savedRating.setHeadNm(loginUser.getUserNm());
|
||||
savedRating.setHeadApprvDt(LocalDateTime.now());
|
||||
savedRating.setHeadApprv(rating.getHeadApprv());
|
||||
savedRating.setHeadEtc(rating.getHeadEtc());
|
||||
savedRating.setAffairRate(rating.getAffairRate());
|
||||
savedRating.setOrganUp(rating.getOrganUp()==null?"F":rating.getOrganUp());
|
||||
savedRating.setAffairStatus(rating.getHeadApprv());
|
||||
if(savedRating.getOrganUp().equals("T")){
|
||||
List<String> organList = loginUser.getUpOrganCdList();
|
||||
String upOrgan = organList.get(organList.indexOf(savedRating.getRatingOrgan())-1);
|
||||
AffairRating upRating = new AffairRating();
|
||||
upRating.setRatingOrgan(upOrgan);
|
||||
upRating.setAffairKey(savedRating.getAffairKey());
|
||||
upRating.setAffairStatus("DST002");
|
||||
affairRatingRepository.save(upRating);
|
||||
}
|
||||
}
|
||||
affairRatingRepository.save(savedRating);
|
||||
}
|
||||
affairRatingRepository.save(savedRating);
|
||||
}
|
||||
return rating.getAffairKey();
|
||||
return ratingList.size()>1?0:ratingList.get(0).getAffairKey();
|
||||
}
|
||||
|
||||
public FileInfo selectAffairFile(Integer parentKey, Integer fileSeq) {
|
||||
|
|
|
|||
|
|
@ -60,6 +60,10 @@
|
|||
</sql>
|
||||
<select id="selectAffairBoardList" resultType="AffairBoard" parameterType="AffairBoard">
|
||||
select a.affair_key,
|
||||
a.affair_type1,
|
||||
a.affair_type2,
|
||||
a.affair_type3,
|
||||
a.affair_type4,
|
||||
a.title,
|
||||
a.wrt_organ,
|
||||
a.wrt_part,
|
||||
|
|
|
|||
|
|
@ -15,10 +15,13 @@ $(document).on('click', '#stayTab', function (){
|
|||
$(document).on('click', '#commitTab', function (){
|
||||
location.href = "/affair/commitPage";
|
||||
})
|
||||
$(document).on('click', '.affairTr', function (){
|
||||
$(".trChkBox").prop("checked", false);
|
||||
$(this).find(".trChkBox").prop("checked", true);
|
||||
getAffairViewModal(Number($(this).find(".affairKey").val()));
|
||||
$(document).on('click', '.affairTr', function (event){
|
||||
const target = event.target;
|
||||
if(!(target.className === "apprvTd" || $(target).parents(".apprvTd").length>0)){
|
||||
$(".trChkBox").prop("checked", false);
|
||||
$(this).find(".trChkBox").prop("checked", true);
|
||||
getAffairViewModal(Number($(this).find(".affairKey").val()));
|
||||
}
|
||||
})
|
||||
$(document).on('click', '#addAffairBtn', function (){
|
||||
getAffairEditModal(null)
|
||||
|
|
@ -62,32 +65,66 @@ $(document).on('click', '.apprvBtn', function (){
|
|||
if(confirm($(this).val()+"하시겠습니까?")){
|
||||
const apprvType = $(this).attr("data-apprvtype");
|
||||
$((apprvType === "section"?"#sectionApprv":"#headApprv")).val(affairState)
|
||||
$("#apprvFormRatingOrgan").val($(".ratingOrganCd")[0].value);
|
||||
const formData = new FormData($("#apprvForm")[0]);
|
||||
contentFade("in")
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
data : formData,
|
||||
url : "/affair/affairStateChange",
|
||||
processData: false,
|
||||
contentType: false,
|
||||
beforeSend: function (xhr){
|
||||
xhr.setRequestHeader($("[name='_csrf_header']").val(), $("[name='_csrf']").val());
|
||||
},
|
||||
success : function(result) {
|
||||
alert("저장되었습니다")
|
||||
getAffairViewModal(result);
|
||||
contentFade("out");
|
||||
},
|
||||
error : function(xhr, status) {
|
||||
alert("저장에 실패하였습니다.");
|
||||
contentFade("out");
|
||||
const ratingList = [];
|
||||
const apprv = {}
|
||||
for (let data of formData.entries()) {
|
||||
if(data[0] !== undefined){
|
||||
apprv[data[0]] = data[1];
|
||||
}
|
||||
})
|
||||
}
|
||||
ratingList.push(apprv);
|
||||
affairStateChange(ratingList);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
$(document).on('click', '#tableApprvBtn', function (){
|
||||
const ratingList = [];
|
||||
const apprvAuth = $(this).attr("data-apprvauth")
|
||||
$.each($(".apprvTd"), function (idx, el) {
|
||||
if (apprvAuth === "APC003" || apprvAuth === "APC004") {
|
||||
const chkbox = $(el).find(".apprvChkbox:checked")
|
||||
if(chkbox.length>0){
|
||||
const affairRating = {};
|
||||
affairRating["affairKey"] = Number($(el).find(".affairKey").val());
|
||||
affairRating["sectionApprv"] = chkbox.val();
|
||||
ratingList.push(affairRating);
|
||||
}
|
||||
} else {
|
||||
const chkbox = $(el).find(".apprvChkbox:checked")
|
||||
const selectorValue = $(el).find(".ratingSelector").val()
|
||||
if(chkbox.length>0){
|
||||
const affairRating = {};
|
||||
affairRating["affairKey"] = Number($(el).find(".affairKey").val());
|
||||
affairRating["headApprv"] = chkbox.val();
|
||||
if(selectorValue !== ""){
|
||||
affairRating["affairRate"] = selectorValue;
|
||||
affairRating["organUp"] = $(el).find(".organUpChkBox").prop("checked")?"T":"F";
|
||||
}
|
||||
ratingList.push(affairRating);
|
||||
}
|
||||
}
|
||||
})
|
||||
affairStateChange(ratingList);
|
||||
})
|
||||
|
||||
$(document).on('change', '.apprvChkbox', function (){
|
||||
if(this.value === "DST006"){
|
||||
const apprvTd = $(this).parents(".apprvTd");
|
||||
apprvTd.find(".ratingSelector").attr("disabled", false)
|
||||
apprvTd.find(".organUpChkBox").attr("disabled", false)
|
||||
}else if(this.value === "DST005"){
|
||||
const apprvTd = $(this).parents(".apprvTd");
|
||||
const ratingSelector = apprvTd.find(".ratingSelector")
|
||||
ratingSelector.val("");
|
||||
ratingSelector.attr("disabled", true)
|
||||
const organUpChkBox = apprvTd.find(".organUpChkBox")
|
||||
organUpChkBox.prop("checked", false);
|
||||
organUpChkBox.attr("disabled", true)
|
||||
}
|
||||
})
|
||||
|
||||
function getAffairViewModal(affairKey){
|
||||
$.ajax({
|
||||
url: '/affair/affairViewModal',
|
||||
|
|
@ -174,7 +211,31 @@ function saveAffair(affairStatus){
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
function affairStateChange(ratingList){
|
||||
contentFade("in")
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : "/affair/affairStateChange",
|
||||
data : JSON.stringify(ratingList),
|
||||
contentType: 'application/json',
|
||||
beforeSend: function (xhr){
|
||||
xhr.setRequestHeader($("[name='_csrf_header']").val(), $("[name='_csrf']").val());
|
||||
},
|
||||
success : function(result) {
|
||||
alert("저장되었습니다")
|
||||
contentFade("out");
|
||||
if(result !== 0){
|
||||
getAffairViewModal(result);
|
||||
}else{
|
||||
location.reload()
|
||||
}
|
||||
},
|
||||
error : function(xhr, status) {
|
||||
alert("저장에 실패하였습니다.");
|
||||
contentFade("out");
|
||||
}
|
||||
})
|
||||
}
|
||||
function contentCheck(){
|
||||
let flag = true;
|
||||
if(!$("#title").val()){
|
||||
|
|
|
|||
|
|
@ -82,6 +82,10 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>분야1</th>
|
||||
<th>분야2</th>
|
||||
<th>분야3</th>
|
||||
<th>분야4</th>
|
||||
<th>제목</th>
|
||||
<th>관서</th>
|
||||
<th>부서</th>
|
||||
|
|
@ -89,7 +93,7 @@
|
|||
<th>작성일시</th>
|
||||
<th>첨부파일</th>
|
||||
<th>상태</th>
|
||||
<th:block th:if="${page ne 'main'}">
|
||||
<th:block th:if="${page ne 'main' and apprvAuth ne null}">
|
||||
<th>평가</th>
|
||||
<th:block th:if="${page eq 'commit'}">
|
||||
<th>상보</th>
|
||||
|
|
@ -101,6 +105,18 @@
|
|||
<tr class="affairTr" th:each="affair:${affairList}">
|
||||
<input type="hidden" class="affairKey" th:value="${affair.affairKey}">
|
||||
<td><input type="checkbox" class="trChkBox"></td>
|
||||
<th:block th:each="commonCode:${session.commonCode.get('DC01')}">
|
||||
<td th:if="${affair.affairType1 eq commonCode.itemCd}" th:text="${commonCode.itemValue}"></td>
|
||||
</th:block>
|
||||
<th:block th:each="commonCode:${session.commonCode.get('DC02')}">
|
||||
<td th:if="${affair.affairType2 eq commonCode.itemCd}" th:text="${commonCode.itemValue}"></td>
|
||||
</th:block>
|
||||
<th:block th:each="commonCode:${session.commonCode.get('DC03')}">
|
||||
<td th:if="${affair.affairType3 eq commonCode.itemCd}" th:text="${commonCode.itemValue}"></td>
|
||||
</th:block>
|
||||
<th:block th:each="commonCode:${session.commonCode.get('DC04')}">
|
||||
<td th:if="${affair.affairType4 eq commonCode.itemCd}" th:text="${commonCode.itemValue}"></td>
|
||||
</th:block>
|
||||
<td th:text="${affair.title}"></td>
|
||||
<th:block th:each="commonCode:${session.commonCode.get('OG')}">
|
||||
<td th:if="${affair.wrtOrgan eq commonCode.itemCd}" th:text="${commonCode.itemValue}"></td>
|
||||
|
|
@ -111,29 +127,46 @@
|
|||
<td th:text="${affair.wrtUserNm}"></td>
|
||||
<td th:text="${#temporals.format(affair.wrtDt, 'yyyy-MM-dd HH:mm')}"></td>
|
||||
<td th:text="${affair.fileCnt eq null?'파일 없음':#strings.concat(affair.fileCnt,' 건')}"></td>
|
||||
<td th:if="${affair.affairStatus eq 'DST001'}">임시저장</td>
|
||||
<td th:if="${affair.affairStatus eq 'DST002'}">결재대기</td>
|
||||
<td th:if="${affair.affairStatus eq 'DST003'}">계장반려</td>
|
||||
<td th:if="${affair.affairStatus eq 'DST004'}">계장결재</td>
|
||||
<td th:if="${affair.affairStatus eq 'DST005'}">부장반려</td>
|
||||
<td th:if="${affair.affairStatus eq 'DST006'}">부장결재</td>
|
||||
<th:block th:each="commonCode:${session.commonCode.get('DST')}">
|
||||
<td th:if="${affair.affairStatus eq commonCode.itemCd}" th:text="${commonCode.itemValue}"></td>
|
||||
</th:block>
|
||||
<th:block th:if="${page eq 'stay'}">
|
||||
<th:block th:if="${apprvAuth eq 'APC004' or apprvAuth eq 'APC003'}">
|
||||
<td>
|
||||
<input type="radio" th:id="|apprvChkbox${affair.affairKey}DST004|" th:name="|apprvChkbox${affair.affairKey}|" value="DST004">
|
||||
<td class="apprvTd">
|
||||
<input type="hidden" class="affairKey" th:value="${affair.affairKey}">
|
||||
<input type="radio" class="apprvChkbox" th:id="|apprvChkbox${affair.affairKey}DST004|" th:name="|apprvChkbox${affair.affairKey}|" value="DST004">
|
||||
<label th:for="|apprvChkbox${affair.affairKey}DST004|">결재</label>
|
||||
<input type="radio" th:id="|apprvChkbox${affair.affairKey}DST003|" th:name="|apprvChkbox${affair.affairKey}|" value="DST003">
|
||||
<input type="radio" class="apprvChkbox" th:id="|apprvChkbox${affair.affairKey}DST003|" th:name="|apprvChkbox${affair.affairKey}|" value="DST003">
|
||||
<label th:for="|apprvChkbox${affair.affairKey}DST003|">반려</label>
|
||||
<input type="radio" th:id="|apprvChkbox${affair.affairKey}|" th:name="|apprvChkbox${affair.affairKey}|" value="" checked>
|
||||
<label th:for="|apprvChkbox${affair.affairKey}|">해제</label>
|
||||
</td>
|
||||
</th:block>
|
||||
<th:block th:if="${apprvAuth eq 'APC002' or apprvAuth eq 'APC001'}">
|
||||
<td>
|
||||
<select class="form-select form-select-sm">
|
||||
<option>선택</option>
|
||||
<th:block th:each="ratingCode:${ratingCodeList}">
|
||||
<option th:value="${ratingCode.itemCd}" th:text="${ratingCode.itemValue}"></option>
|
||||
</th:block>
|
||||
</select>
|
||||
<td class="apprvTd">
|
||||
<input type="hidden" class="affairKey" th:value="${affair.affairKey}">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-auto">
|
||||
<input type="radio" class="apprvChkbox" th:id="|apprvChkbox${affair.affairKey}DST006|" th:name="|apprvChkbox${affair.affairKey}|" value="DST006">
|
||||
<label th:for="|apprvChkbox${affair.affairKey}DST006|">결재</label>
|
||||
<input type="radio" class="apprvChkbox" th:id="|apprvChkbox${affair.affairKey}DST005|" th:name="|apprvChkbox${affair.affairKey}|" value="DST005">
|
||||
<label th:for="|apprvChkbox${affair.affairKey}DST005|">반려</label>
|
||||
<input type="radio" th:id="|apprvChkbox${affair.affairKey}|" th:name="|apprvChkbox${affair.affairKey}|" value="" checked>
|
||||
<label th:for="|apprvChkbox${affair.affairKey}|">해제</label>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<select class="form-select form-select-sm ratingSelector" disabled>
|
||||
<option value="">선택</option>
|
||||
<th:block th:each="ratingCode:${ratingCodeList}">
|
||||
<option th:value="${ratingCode.itemCd}" th:text="${ratingCode.itemValue}"></option>
|
||||
</th:block>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-auto" th:unless="${userOrgan eq 'OG001'}">
|
||||
<label th:for="|organUp${affair.affairKey}|">상보</label>
|
||||
<input type="checkbox" class="organUpChkBox" th:id="|organUp${affair.affairKey}|" value="T" disabled>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</th:block>
|
||||
</th:block>
|
||||
|
|
@ -183,7 +216,7 @@
|
|||
</nav>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<input type="button" class="btn btn-warning" value="결재" id="addAffairBtn" th:if="${page eq 'stay' and apprvAuth ne null}">
|
||||
<input type="button" class="btn btn-warning" value="결재" id="tableApprvBtn" th:if="${page eq 'stay' and apprvAuth ne null}" th:data-apprvauth="${apprvAuth}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -142,7 +142,6 @@
|
|||
<th:block th:each="rate:${affair.rateList}">
|
||||
<div class="row py-1">
|
||||
<div class="col-auto">
|
||||
<input type="hidden" class="ratingOrganCd" th:value="${rate.ratingOrgan}">
|
||||
<th:block th:each="commonCode:${session.commonCode.get('OG')}">
|
||||
<p th:if="${commonCode.itemCd eq rate.ratingOrgan}" th:text="${commonCode.itemValue}"></p>
|
||||
</th:block>
|
||||
|
|
@ -164,7 +163,7 @@
|
|||
<span th:text="|결재일시: ${#temporals.format(rate.sectionApprvDt, 'yyyy-MM-dd HH:mm:ss')}|"></span>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<span th:text="|기타의견: ${rate.sectionEtc}|"></span>
|
||||
<span th:text="|기타의견: ${rate.sectionEtc eq null?'':rate.sectionEtc}|"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" th:if="${rate.headApprv ne null}">
|
||||
|
|
@ -185,7 +184,7 @@
|
|||
<span th:text="|결재일시: ${#temporals.format(rate.headApprvDt, 'yyyy-MM-dd HH:mm:ss')}|"></span>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<span th:text="|기타의견: ${rate.headEtc}|"></span>
|
||||
<span th:text="|기타의견: ${rate.headEtc eq null?'':rate.headEtc}|"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -196,12 +195,11 @@
|
|||
<div class="col-12" th:if="${apprvAuth ne null}">
|
||||
<form action="#" method="post" id="apprvForm">
|
||||
<input type="hidden" name="affairKey" th:value="${affair.affairKey}">
|
||||
<input type="hidden" name="ratingOrgan" id="apprvFormRatingOrgan">
|
||||
<th:block th:if="${(apprvAuth eq 'APC003' or apprvAuth eq 'APC004') and affair.affairStatus eq 'DST002'}">
|
||||
<input type="hidden" name="sectionApprv" id="sectionApprv">
|
||||
<div class="row">
|
||||
<div class="col-10">
|
||||
<input type="text" class="form-control form-control-sm" name="sectionEtc" placeholder="추가의견, 반려사유 기입">
|
||||
<input type="text" class="form-control form-control-sm etc" name="sectionEtc" placeholder="추가의견, 반려사유 기입">
|
||||
<input type="text" class="d-none" id="submitPrevention">
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
|
|
@ -216,7 +214,7 @@
|
|||
<input type="hidden" name="headApprv" id="headApprv">
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<input type="text" class="form-control form-control-sm" name="headEtc" placeholder="추가의견, 반려사유 기입">
|
||||
<input type="text" class="form-control form-control-sm etc" name="headEtc" placeholder="추가의견, 반려사유 기입">
|
||||
<input type="text" class="d-none" id="submitPrevention">
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
|
|
@ -227,7 +225,7 @@
|
|||
</th:block>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="col-auto" th:unless="${userOrgan eq 'OG001'}">
|
||||
<label for="organUp" class="form-check-label">상보여부</label>
|
||||
<input type="checkbox" id="organUp" name="organUp" value="T">
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue