재부과 그리드 테스트, 기초 틀 잡는중...

dev
박성영 2 months ago
parent dade725948
commit 30481bad42

@ -60,7 +60,7 @@ public class DateUtil {
public static String getCurrentDateAddMonths(String pattern, int months) {
LocalDate now = LocalDate.now();
return now.plusMonths(months).format(DateTimeFormatter.ofPattern(pattern));
}
}
/**
*
@ -301,6 +301,31 @@ public class DateUtil {
return date.plusYears(years);
}
/**
* //
*
* @param pattern (: "yyyy-MM-dd", "yyyyMMdd")
* @param type (Y: , M: , D: )
* @param amount (: , : )
* @return
*/
public static String getCurrentDateAdd(String pattern, String type, int amount) {
LocalDate now = LocalDate.now();
LocalDate result;
if ("Y".equalsIgnoreCase(type) || "year".equalsIgnoreCase(type)) {
result = now.plusYears(amount);
} else if ("M".equalsIgnoreCase(type) || "month".equalsIgnoreCase(type)) {
result = now.plusMonths(amount);
} else if ("D".equalsIgnoreCase(type) || "day".equalsIgnoreCase(type)) {
result = now.plusDays(amount);
} else {
result = now;
}
return result.format(DateTimeFormatter.ofPattern(pattern));
}
/**
*
* @param startDate

@ -124,4 +124,31 @@ public class LevyRelevyController {
return ApiResponseUtil.successWithGrid(list, paramVO);
}
/**
* chain AJAX
* chain .
*
* @param paramVO VO (crdnYr, crdnNo, frstCrdnYr, frstCrdnNo )
* @return chain ResponseEntity
*/
@Operation(summary = "재부과 chain 목록 조회 (AJAX)", description = "재부과 chain 목록을 조회하고 JSON 형식으로 반환합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "재부과 chain 목록 조회 성공"),
@ApiResponse(responseCode = "400", description = "재부과 chain 목록 조회 실패"),
@ApiResponse(description = "오류로 인한 실패")
})
@PostMapping("/relevyChain.ajax")
public ResponseEntity<?> relevyChainAjax(@ModelAttribute LevyRelevyVO paramVO) {
log.debug("재부과 chain 목록 조회 - crdnYr: {}, crdnNo: {}, frstCrdnYr: {}, frstCrdnNo: {}",
paramVO.getCrdnYr(), paramVO.getCrdnNo(), paramVO.getFrstCrdnYr(), paramVO.getFrstCrdnNo());
// 재부과 chain 목록 조회
List<LevyRelevyVO> list = service.selectRelevyChainList(paramVO);
// 총 개수 설정
paramVO.setTotalCount(list.size());
return ApiResponseUtil.successWithGrid(list, paramVO);
}
}

@ -34,5 +34,11 @@ public interface LevyRelevyMapper {
*/
int selectListTotalCount(LevyRelevyVO vo);
/**
* chain . ( chain)
* @param vo VO (crdnYr, crdnNo, frstCrdnYr, frstCrdnNo )
* @return chain
*/
List<LevyRelevyVO> selectRelevyChainList(LevyRelevyVO vo);
}

@ -33,5 +33,12 @@ public interface LevyRelevyService {
*/
int selectListTotalCount(LevyRelevyVO vo);
/**
* chain . ( chain)
*
* @param vo VO (crdnYr, crdnNo, frstCrdnYr, frstCrdnNo )
* @return chain
*/
List<LevyRelevyVO> selectRelevyChainList(LevyRelevyVO vo);
}

@ -51,4 +51,15 @@ public class LevyRelevyServiceImpl extends EgovAbstractServiceImpl implements Le
return mapper.selectListTotalCount(vo);
}
/**
* chain . ( chain)
*
* @param vo VO (crdnYr, crdnNo, frstCrdnYr, frstCrdnNo )
* @return chain
*/
@Override
public List<LevyRelevyVO> selectRelevyChainList(LevyRelevyVO vo) {
return mapper.selectRelevyChainList(vo);
}
}

@ -134,4 +134,85 @@
</if>
</select>
<!-- 재부과 chain 목록 조회 (최초 단속부터 자기 자신 제외한 chain) -->
<select id="selectRelevyChainList" parameterType="LevyRelevyVO" resultType="LevyRelevyVO">
/* LevyRelevyMapper.selectRelevyChainList : 재부과 chain 목록 조회 */
SELECT
c.CRDN_YR, /* 단속 연도 */
c.CRDN_NO, /* 단속 번호 */
c.SGG_CD, /* 시군구 코드 */
sgg.CD_NM AS SGG_CD_NM,
c.RGN_SE_CD, /* 지역 구분 코드 */
rgn.CD_NM AS RGN_SE_CD_NM,
c.DSCL_MTHD_CD, /* 단속 방법 코드 */
dscl.CD_NM AS DSCL_MTHD_CD_NM,
c.DSCL_YMD, /* 적발 일자 */
c.EXMNR, /* 조사원 */
c.RMRK, /* 비고 */
c.DSPS_BFHD_BGNG_YMD, /* 사전처분 시작일 */
c.DSPS_BFHD_END_YMD, /* 사전처분 종료일 */
c.CRC_CMD_BGNG_YMD, /* 시정명령 시작일 */
c.CRC_CMD_END_YMD, /* 시정명령 종료일 */
c.CRC_URG_BGNG_YMD, /* 시정촉구 시작일 */
c.CRC_URG_END_YMD, /* 시정촉구 종료일 */
c.LEVY_PRVNTC_BGNG_YMD, /* 부과예고 시작일 */
c.LEVY_PRVNTC_END_YMD, /* 부과예고 종료일 */
c.LEVY_BGNG_YMD, /* 부과 시작일 */
c.LEVY_END_YMD, /* 부과 종료일 */
c.PAY_URG_BGNG_YMD, /* 납부촉구 시작일 */
c.PAY_URG_END_YMD, /* 납부촉구 종료일 */
c.FRST_CRDN_YR, /* 최초 단속 연도 */
c.FRST_CRDN_NO, /* 최초 단속 번호 */
c.RELEVY_YN, /* 재과 여부 */
c.AGRVTN_LEVY_TRGT_YN, /* 가중 부과 대상 여부 */
c.CRDN_PRCS_STTS_CD, /* 단속 처리 상태 코드 */
stts.CD_NM AS CRDN_PRCS_STTS_CD_NM,
c.CRDN_PRCS_YMD, /* 단속 처리 일자 */
c.REG_DT,
c.RGTR,
u.USER_ACNT AS RGTR_ACNT,
u.USER_NM AS RGTR_NM,
p.LOTNO_WHOL_ADDR, /* 지번 전체 주소 */
p.STDG_EMD_CD, /* 법정동 읍면동 코드 */
emd.CD_NM AS STDG_EMD_CD_NM,
p.ZIP,
(SELECT GROUP_CONCAT(DISTINCT o2.FLNM SEPARATOR ', ')
FROM tb_ownr_info oi2
LEFT JOIN tb_ownr o2 ON o2.OWNR_ID = oi2.OWNR_ID AND o2.DEL_YN = 'N'
WHERE oi2.CRDN_YR = c.CRDN_YR
AND oi2.CRDN_NO = c.CRDN_NO
AND oi2.DEL_YN = 'N') AS OWNR_NAMS,
(SELECT GROUP_CONCAT(DISTINCT o2.FLNM SEPARATOR ', ')
FROM tb_actr_info ai
LEFT JOIN tb_ownr o2 ON o2.OWNR_ID = ai.OWNR_ID AND o2.DEL_YN = 'N'
WHERE ai.CRDN_YR = c.CRDN_YR
AND ai.CRDN_NO = c.CRDN_NO
AND ai.DEL_YN = 'N') AS ACTR_NAMS,
a.ACT_TYPE_CD, /* 행위 유형 코드 */
CASE WHEN (SELECT COUNT(1) FROM tb_act_info a2 WHERE a2.CRDN_YR = a.CRDN_YR AND a2.CRDN_NO = a.CRDN_NO AND a2.DEL_YN='N') > 1 THEN
CONCAT(act.VLTN_BDST, ' 등 ', (SELECT COUNT(1) FROM tb_act_info a2 WHERE a2.CRDN_YR = a.CRDN_YR AND a2.CRDN_NO = a.CRDN_NO AND a2.DEL_YN='N'), '건')
ELSE act.VLTN_BDST END ACT_TYPE_CD_NM,
a.USG_IDX_CD, /* 용도 지수 코드 */
usg.USG_NM AS USG_IDX_CD_NM
FROM tb_crdn c
LEFT JOIN tb_cd_detail sgg ON sgg.CD_GROUP_ID = 'ORG_CD' AND sgg.CD_ID = c.SGG_CD
LEFT JOIN tb_cd_detail rgn ON rgn.CD_GROUP_ID = 'RGN_SE_CD' AND rgn.CD_ID = c.RGN_SE_CD
LEFT JOIN tb_cd_detail dscl ON dscl.CD_GROUP_ID = 'DSCL_MTHD_CD' AND dscl.CD_ID = c.DSCL_MTHD_CD
LEFT JOIN tb_cd_detail stts ON stts.CD_GROUP_ID = 'CRDN_PRCS_STTS_CD' AND stts.CD_ID = c.CRDN_PRCS_STTS_CD
LEFT JOIN tb_user u ON u.USER_ID = c.RGTR AND u.USE_YN = 'Y'
LEFT JOIN tb_pstn_info p ON p.CRDN_YR = c.CRDN_YR AND p.CRDN_NO = c.CRDN_NO AND p.DEL_YN = 'N'
LEFT JOIN tb_cd_detail emd ON emd.CD_GROUP_ID = 'STDG_EMD_CD' AND emd.CD_ID = p.STDG_EMD_CD
LEFT Join tb_act_info a ON a.CRDN_YR = c.CRDN_YR and a.CRDN_NO = c.CRDN_NO AND a.DEL_YN = 'N' AND a.ACT_NO = (SELECT MIN(a1.ACT_NO) FROM tb_act_info a1 WHERE a1.CRDN_YR = a.CRDN_YR AND a1.CRDN_NO = a.CRDN_NO AND a1.DEL_YN='N')
LEFT JOIN tb_act_type act ON act.ACT_TYPE_CD = a.ACT_TYPE_CD
LEFT JOIN tb_usg_idx usg ON usg.USG_IDX_CD = a.USG_IDX_CD AND usg.DEL_YN = 'N'
WHERE c.DEL_YN = 'N'
AND (
(c.FRST_CRDN_YR = #{frstCrdnYr} AND c.FRST_CRDN_NO = #{frstCrdnNo})
or
(c.CRDN_YR = #{frstCrdnYr} AND c.CRDN_NO = #{frstCrdnNo})
)
AND NOT (c.CRDN_YR = #{crdnYr} AND c.CRDN_NO = #{crdnNo})
ORDER BY c.CRDN_YR DESC, c.CRDN_NO ASC
</select>
</mapper>

@ -60,4 +60,10 @@
<function-signature>java.lang.String formatDateString(java.lang.String)</function-signature>
</function>
<function>
<name>getCurrentDateAdd</name>
<function-class>egovframework.util.DateUtil</function-class>
<function-signature>java.lang.String getCurrentDateAdd(java.lang.String, java.lang.String, int)</function-signature>
</function>
</taglib>

@ -4,6 +4,27 @@
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="dateUtil" uri="http://egovframework.go.kr/functions/date-util" %>
<%--
재부과 관련 기초 그리드 조회 프로그램
src/main/webapp/WEB-INF/views/levy/levyRelevy/list.jsp
src/main/java/go/kr/project/levy/levyRelevy/controller/LevyRelevyController.java
src/main/java/go/kr/project/levy/levyRelevy/mapper/LevyRelevyMapper.java
src/main/java/go/kr/project/levy/levyRelevy/model/LevyRelevyVO.java
src/main/java/go/kr/project/levy/levyRelevy/service/impl/LevyRelevyServiceImpl.java
src/main/java/go/kr/project/levy/levyRelevy/service/LevyRelevyService.java
src/main/resources/mybatis/mapper/levy/levyRelevy/RevyRelevyMapper_maria.xml
tb_crdn.FRST_CRDN_YR:최초 단속 연도
tb_crdn.FRST_CRDN_NO:최초 단속 번호
tb_crdn.RELEVY_TRGT_CRDN_YR:재부과 대상 단속 연도,자신의 바로 위 부모
tb_crdn.RELEVY_TRGT_CRDN_NO:재부과 대상 단속 번호,자신의 바로 위 부모
구현 대상, 일부 기능은 구현 완료, 하위 그리드에 대한 내용은 구현안되어 있음
1. 이메뉴는 재부과 대상(schCrdnYr : 올해-1년) 메인 리스트를 보여준뒤, focus 가 되면
2. 하위 그리드(현재 구현안되어 있음)에 최초 단속부터, 자기 자신을 제외한 chain 단속(재부과) 목록을 부여줘야해
--%>
<!-- Main body -->
<div class="main_body">
<section id="section8" class="main_bars">
@ -20,7 +41,7 @@
<ul class="lef">
<li class="th">단속 년도</li>
<li>
<input type="text" id="schCrdnYr" name="schCrdnYr" maxlength="4" class="input calender yearpicker" style="width: 80px;" autocomplete="off" value="${dateUtil:getCurrentDateTime('yyyy')}"/>
<input type="text" id="schCrdnYr" name="schCrdnYr" maxlength="4" class="input calender yearpicker" style="width: 80px;" autocomplete="off" value="${dateUtil:getCurrentDateAdd('yyyy', 'year', -1)}"/>
</li>
<li class="th">단속 번호</li>
<li>
@ -110,6 +131,18 @@
</div>
</div>
</div>
<div class="row" style="margin-top: 20px;">
<div class="col-sm-12">
<div class="box_column">
<ul class="box_title" style="display: flex; justify-content: space-between; align-items: center;">
<li class="tit">재부과 이력 (선택된 단속의 최초 단속부터 현재까지)</li>
</ul>
<div class="containers">
<div id="gridDetail"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@ -407,6 +440,18 @@
this.instance.on('focusChange', function(ev) {
LevyRelevyList.selectedRow = self.instance.getRow(ev.rowKey);
// 하위 그리드에 재부과 chain 데이터 로드
if (LevyRelevyList.selectedRow) {
// 파라미터 저장
LevyRelevyList.gridDetail.currentCrdnYr = LevyRelevyList.selectedRow.crdnYr;
LevyRelevyList.gridDetail.currentCrdnNo = LevyRelevyList.selectedRow.crdnNo;
LevyRelevyList.gridDetail.currentFrstCrdnYr = LevyRelevyList.selectedRow.frstCrdnYr;
LevyRelevyList.gridDetail.currentFrstCrdnNo = LevyRelevyList.selectedRow.frstCrdnNo;
// 그리드 데이터 요청
LevyRelevyList.gridDetail.instance.readData(1);
}
});
// 행 선택 이벤트
@ -439,6 +484,160 @@
},
/**
* 하위 그리드 관련 객체 (재부과 chain)
*/
gridDetail: {
/**
* 그리드 인스턴스
*/
instance: null,
/**
* 현재 선택된 행의 정보 저장
*/
currentCrdnYr: null,
currentCrdnNo: null,
currentFrstCrdnYr: null,
currentFrstCrdnNo: null,
/**
* 그리드 설정 초기화
* @returns {Object} 그리드 설정 객체
*/
initConfig: function() {
// 데이터 소스 설정
var dataSource = this.createDataSource();
// 그리드 설정 객체 생성
var gridConfig = new XitTuiGridConfig();
// 기본 설정
gridConfig.setOptDataSource(dataSource); // 데이터소스 연결
gridConfig.setOptGridId('gridDetail'); // 그리드를 출력할 Element ID
gridConfig.setOptGridHeight(200); // 그리드 높이(단위: px)
gridConfig.setOptRowHeight(30); // 그리드 행 높이(단위: px)
gridConfig.setOptRowHeaderType(''); // 행 첫번째 셀 타입 비활성화
gridConfig.setOptUseClientSort(true); // 클라이언트 정렬 사용
gridConfig.setOptColumns(this.getGridColumns());
return gridConfig;
},
/**
* 데이터 소스 생성
* @returns {Object} 데이터 소스 설정 객체
*/
createDataSource: function() {
var self = this;
return {
api: {
readData: {
url: '<c:url value="/levy/levyRelevy/relevyChain.ajax"/>',
method: 'POST',
contentType: 'application/x-www-form-urlencoded',
processData: true
}
},
initialRequest: false, // 초기 데이터 요청 여부
serializer: function(params) {
var defaultParams = $.param(params);
var searchParams = $.param({
crdnYr: self.currentCrdnYr,
crdnNo: self.currentCrdnNo,
frstCrdnYr: self.currentFrstCrdnYr,
frstCrdnNo: self.currentFrstCrdnNo
});
return defaultParams + '&' + searchParams;
}
};
},
/**
* 그리드 컬럼 정의
* @returns {Array} 그리드 컬럼 배열
*/
getGridColumns: function() {
return [
{
header: '순번',
name: '_rowNum',
align: 'center',
width: 60,
sortable: false,
formatter: function(e) {
return e.row.rowKey + 1;
}
},
{ header: '단속년도', name: 'crdnYr', align: 'center', width: 80 },
{ header: '단속번호', name: 'crdnNo', align: 'center', width: 90 },
{ header: '법정동', name: 'stdgEmdCdNm', align: 'center', width: 90 },
{ header: '지역구분', name: 'rgnSeCdNm', align: 'center', width: 100 },
{ header: '적발방법', name: 'dsclMthdCdNm', align: 'center', width: 120 },
{
header: '적발일자',
name: 'dsclYmd',
align: 'center',
width: 100,
formatter: function (e) {
return e.value ? moment(e.value).format('YYYY-MM-DD') : '';
}
},
{ header: '조사원', name: 'exmnr', align: 'left', width: 130 },
{
header: '재부과여부',
name: 'relevyYn',
align: 'center',
width: 80,
formatter: function(e) {
return e.value === 'Y' ? '재부과' : '일반';
}
},
{ header: '진행단계', name: 'crdnPrcsSttsCdNm', align: 'center', width: 100 },
{
header: '위치',
name: 'lotnoWholAddr',
align: 'left',
minWidth: 250,
formatter: function(e) {
return e.value;
}
},
{
header: '부과예고 일자',
name: 'levyPrvntcBgngYmd',
align: 'center',
width: 120,
formatter: function (e) {
return e.value ? moment(e.value).format('YYYY-MM-DD') : '';
}
},
{
header: '부과 일자',
name: 'levyBgngYmd',
align: 'center',
width: 120,
formatter: function (e) {
return e.value ? moment(e.value).format('YYYY-MM-DD') : '';
}
}
];
},
/**
* 그리드 인스턴스 생성
*/
create: function() {
var gridConfig = this.initConfig();
var Grid = tui.Grid;
this.instance = gridConfig.instance(Grid);
// 그리드 테마 설정
Grid.applyTheme('striped');
},
},
/**
* 목록 현재 페이징 새로고침
*/
@ -531,10 +730,13 @@
* 모듈 초기화
*/
init: function() {
// 그리드 생성
// 메인 그리드 생성
this.grid.create();
// 하위 그리드 생성 (재부과 chain)
this.gridDetail.create();
// 이벤트 핸들러 설정
this.eventBindEvents();

Loading…
Cancel
Save