단속 > 단속 등록&열람

init, 최초 기능 진행중...
dev
박성영 4 months ago
parent 9712bbd541
commit 608ca16a2f

@ -58,9 +58,6 @@ public class CommonCodeController {
return ApiResponseUtil.success(codeDetailList);
}
/**
*
*/
/**
* AJAX
*

@ -24,8 +24,25 @@ public class CmmnCodeSearchVO {
private String searchCdId;
private String searchCdNm;
private String searchAttribute1;
private String searchAttribute2;
private String searchAttribute3;
private String searchAttribute4;
private String searchAttribute5;
/** 사용유무 */
private String searchUseYn;
/** 등록일시 시작일 */
private String searchRegDttmStart;
/** 등록일시 종료일 */
private String searchRegDttmEnd;
/** 등록자 */
private String searchRgtr;
/** 수정일시 시작일 */
private String searchMdfcnDttmStart;
/** 수정일시 종료일 */
private String searchMdfcnDttmEnd;
/** 수정자 */
private String searchMdfr;
/** 정렬컬럼 */
private String sortColumn;

@ -57,13 +57,15 @@ public class CrdnRegistAndViewController {
public String list( Model model ) {
log.debug("단속 목록 화면 요청");
//지역구분 코드 조회
CmmnCodeSearchVO rgnSeCdSearchVO = CmmnCodeSearchVO.builder()
.searchCdGroupId("RGN_SE_CD")
.sortColumn("CD_NM")
.sortColumn("SORT_ORDR")
.sortAscending(true)
.build();
model.addAttribute("regionList", commonCodeService.selectCodeDetailList(rgnSeCdSearchVO));
//적발방법 코드 조회
CmmnCodeSearchVO dsclMthdCdSearchVO = CmmnCodeSearchVO.builder()
.searchCdGroupId("DSCL_MTHD_CD")
.sortColumn("CD_NM")

@ -70,4 +70,18 @@ public interface CrdnRegistAndViewMapper {
*/
int selectDuplicateCheck(CrdnRegistAndViewVO vo);
/**
* 퀀 .
* @param sequenceName 퀀 (seq_crdn_no_YYYY )
* @return 퀀 (0 , 1 )
*/
int checkSequenceExists(String sequenceName);
/**
* 퀀 .
* @param sequenceName 퀀 (seq_crdn_no_YYYY )
* @return
*/
void createSequence(String sequenceName);
}

@ -105,6 +105,9 @@ public class CrdnRegistAndViewServiceImpl extends EgovAbstractServiceImpl implem
vo.setRelevyYn("N");
}
// 년도별 시퀀스 존재 여부 확인 및 생성
ensureSequenceExists(currentYear);
// 등록자 정보 설정 및 등록 수행
vo.setRgtr(SessionUtil.getUserId());
int result = mapper.insert(vo);
@ -219,4 +222,24 @@ public class CrdnRegistAndViewServiceImpl extends EgovAbstractServiceImpl implem
}
}
/**
* 퀀 .
* @param year (YYYY )
*/
private void ensureSequenceExists(String year) {
String sequenceName = "seq_crdn_no_" + year;
log.debug("년도별 시퀀스 확인 - 시퀀스명: {}", sequenceName);
// 시퀀스 존재 여부 확인
int sequenceCount = mapper.checkSequenceExists(sequenceName);
if (sequenceCount == 0) {
log.info("년도별 시퀀스 생성 - 시퀀스명: {}", sequenceName);
// 시퀀스가 존재하지 않으면 생성
mapper.createSequence(sequenceName);
log.debug("년도별 시퀀스 생성 완료 - 시퀀스명: {}", sequenceName);
} else {
log.debug("년도별 시퀀스 이미 존재 - 시퀀스명: {}", sequenceName);
}
}
}

@ -61,6 +61,36 @@
<if test="searchAttribute1 != null and searchAttribute1 != ''">
and ATTRIBUTE1 = #{searchAttribute1}
</if>
<if test="searchAttribute2 != null and searchAttribute2 != ''">
and ATTRIBUTE2 = #{searchAttribute2}
</if>
<if test="searchAttribute3 != null and searchAttribute3 != ''">
and ATTRIBUTE3 = #{searchAttribute3}
</if>
<if test="searchAttribute4 != null and searchAttribute4 != ''">
and ATTRIBUTE4 = #{searchAttribute4}
</if>
<if test="searchAttribute5 != null and searchAttribute5 != ''">
and ATTRIBUTE5 = #{searchAttribute5}
</if>
<if test="searchRegDttmStart != null and searchRegDttmStart != ''">
and REG_DTTM &gt;= #{searchRegDttmStart}
</if>
<if test="searchRegDttmEnd != null and searchRegDttmEnd != ''">
and REG_DTTM &lt;= #{searchRegDttmEnd}
</if>
<if test="searchRgtr != null and searchRgtr != ''">
and RGTR like CONCAT('%', #{searchRgtr}, '%')
</if>
<if test="searchMdfcnDttmStart != null and searchMdfcnDttmStart != ''">
and MDFCN_DTTM &gt;= #{searchMdfcnDttmStart}
</if>
<if test="searchMdfcnDttmEnd != null and searchMdfcnDttmEnd != ''">
and MDFCN_DTTM &lt;= #{searchMdfcnDttmEnd}
</if>
<if test="searchMdfr != null and searchMdfr != ''">
and MDFR like CONCAT('%', #{searchMdfr}, '%')
</if>
order by
<choose>
<when test="sortColumn != null and sortColumn != ''">

@ -157,7 +157,7 @@
DEL_YN
) VALUES (
#{crdnYr},
LPAD(NEXTVAL(CONCAT('seq_crdn_no_', #{crdnYr})), 6, '0'),
LPAD(NEXTVAL('seq_crdn_no_${crdnYr}'), 6, '0'),
#{rgnSeCd},
#{dsclMthdCd},
#{dsclYmd},
@ -237,4 +237,24 @@
AND DEL_YN = 'N'
</select>
<!-- 시퀀스 존재 여부 확인 -->
<select id="checkSequenceExists" parameterType="String" resultType="int">
/* CrdnRegistAndViewMapper.checkSequenceExists : 시퀀스 존재 여부 확인 */
SELECT COUNT(*)
FROM INFORMATION_SCHEMA.SEQUENCES
WHERE SEQUENCE_SCHEMA = DATABASE()
AND SEQUENCE_NAME = #{sequenceName}
</select>
<!-- 시퀀스 생성 -->
<update id="createSequence" parameterType="String">
/* CrdnRegistAndViewMapper.createSequence : 년도별 시퀀스 생성 */
CREATE SEQUENCE IF NOT EXISTS ${sequenceName}
START WITH 1
INCREMENT BY 1
MAXVALUE 999999
MINVALUE 1
CACHE 20
</update>
</mapper>

@ -290,7 +290,7 @@
startView: "years",
minViewMode: "years",
autoclose: true,
language: "ko"
language: "kr"
});
},

@ -356,7 +356,7 @@
startView: "years",
minViewMode: "years",
autoclose: true,
language: "ko"
language: "kr"
});
}
});

@ -17,7 +17,7 @@
<div class="contants_body">
<div class="gs_b_top">
<ul class="lef">
<li class="th">단속 도</li>
<li class="th">단속 도</li>
<li>
<input type="text" id="schCrdnYr" name="schCrdnYr" maxlength="4" class="input calender" style="width: 80px;" autocomplete="off" value="${dateUtil:getCurrentDateTime('yyyy')}"/>
</li>
@ -151,7 +151,7 @@
getGridColumns: function() {
return [
{
header: '단속도',
header: '단속도',
name: 'crdnYr',
align: 'center',
width: 80,

@ -1,6 +1,8 @@
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="dateUtil" uri="http://egovframework.go.kr/functions/date-util" %>
<div class="popup_wrap">
<div class="popup_inner">
@ -12,62 +14,91 @@
<div class="forms_table_non">
<form id="crdnForm" name="crdnForm">
<input type="hidden" id="mode" name="mode" value="${param.mode}" />
<input type="hidden" id="crdnYr" name="crdnYr" value="${data.crdnYr}" />
<input type="hidden" id="crdnNo" name="crdnNo" value="${data.crdnNo}" />
<table>
<colgroup>
<col style="width: 20%;" />
<col style="width: 30%;" />
<col style="width: 20%;" />
<col style="width: 30%;"/>
</colgroup>
<tr>
<th class="th"><span class="required">*</span> 지역구분</th>
<th class="th"><span class="required">*</span>단속 년도</th>
<td>
<c:choose>
<c:when test="${param.mode eq 'C'}">
<input type="text" id="crdnYr" name="crdnYr" class="input" value="${dateUtil:getCurrentDateTime('yyyy')}" readonly/>
</c:when>
<c:otherwise>
<input type="text" id="crdnYr" name="crdnYr" class="input"
value="${data.crdnYr}" readonly/>
</c:otherwise>
</c:choose>
</td>
<th class="th"><span class="required">*</span>단속번호</th>
<td>
<select id="rgnSeCd" name="rgnSeCd" class="select" validation-check="required">
<c:choose>
<c:when test="${param.mode eq 'C'}">
자동채번
</c:when>
<c:otherwise>
<input type="text" id="crdnNo" name="crdnNo" class="input"
value="${data.crdnNo}" readonly/>
</c:otherwise>
</c:choose>
</td>
</tr>
<tr>
<th class="th"><span class="required">*</span> 지역구분</th>
<td colspan="3">
<select id="rgnSeCd" name="rgnSeCd" class="input" validation-check="required">
<option value="">선택하세요</option>
</select>
</td>
</tr>
<tr>
<th class="th"><span class="required">*</span> 적발방법</th>
<td>
<select id="dsclMthdCd" name="dsclMthdCd" class="select" validation-check="required">
<td colspan="3">
<select id="dsclMthdCd" name="dsclMthdCd" class="input" validation-check="required">
<option value="">선택하세요</option>
</select>
</td>
</tr>
<tr>
<th class="th">적발일자</th>
<td>
<input type="text" id="dsclYmd" name="dsclYmd" class="input datepicker"
value="${data.dsclYmd}" maxlength="8" style="width: 120px;" />
<th class="th"><span class="required">*</span> 적발일자</th>
<td colspan="3">
<input type="text" id="dsclYmd" name="dsclYmd" class="input calender datepicker" validation-check="required"
value="${data.dsclYmd}" maxlength="10" style="width: 120px;" autocomplete="off"/>
</td>
</tr>
<tr>
<th class="th">조사원</th>
<td>
<td colspan="3">
<input type="text" id="exmnr" name="exmnr" class="input"
value="${data.exmnr}" maxlength="100" style="width: 200px;" />
value="${data.exmnr}" maxlength="100" />
</td>
</tr>
<tr>
<th class="th"><span class="required">*</span> 법정동</th>
<td>
<select id="stdgEmdCd" name="stdgEmdCd" class="select" validation-check="required">
<td colspan="3">
<select id="stdgEmdCd" name="stdgEmdCd" class="input" validation-check="required">
<option value="">선택하세요</option>
</select>
</td>
</tr>
<tr>
<th class="th"><span class="required">*</span> 재부과여부</th>
<td>
<select id="relevyYn" name="relevyYn" class="select" validation-check="required">
<td colspan="3">
<select id="relevyYn" name="relevyYn" class="input" validation-check="required">
<option value="">선택하세요</option>
<option value="N">일반</option>
<option value="N" selected>신규</option>
<option value="Y">재부과</option>
</select>
</td>
</tr>
<tr>
<th class="th">비고</th>
<td>
<textarea id="rmrk" name="rmrk" class="textarea" rows="3" style="width: 100%;">${data.rmrk}</textarea>
<td colspan="3">
<textarea id="rmrk" name="rmrk" class="textarea" rows="3" maxlength="1000" style="width: 100%;">${data.rmrk}</textarea>
</td>
</tr>
</table>
@ -103,9 +134,9 @@
},
initCodeSelect: function() {
commonCodeSelectAjax('RGN_SE_CD', 'rgnSeCd', '선택하세요');
commonCodeSelectAjax('DSCL_MTHD_CD', 'dsclMthdCd', '선택하세요');
commonCodeSelectAjax('STDG_EMD_CD', 'stdgEmdCd', '선택하세요');
commonCodeSelectAjax('RGN_SE_CD', 'rgnSeCd', '선택하세요', "${data.rgnSeCd == null ? '1':data.rgnSeCd}", {sortColumn:"SORT_ORDR"});
commonCodeSelectAjax('DSCL_MTHD_CD', 'dsclMthdCd', '선택하세요', "${data.dsclMthdCd}", {sortColumn:"CD_NM"});
commonCodeSelectAjax('STDG_EMD_CD', 'stdgEmdCd', '선택하세요', "${data.stdgEmdCd}", {sortColumn:"CD_NM"});
},
setFormData: function() {
@ -128,6 +159,12 @@
$("#btnDelete").on('click', function() {
self.delete();
});
$("#dsclYmd").datepicker({
container: '.popup_inner',
language: "kr"
});
},
save: function() {
@ -151,9 +188,6 @@
} else {
alert(response.message || '처리 중 오류가 발생했습니다.');
}
},
error: function() {
alert('처리 중 오류가 발생했습니다.');
}
});
},
@ -178,35 +212,63 @@
} else {
alert(response.message || '삭제 중 오류가 발생했습니다.');
}
},
error: function() {
alert('삭제 중 오류가 발생했습니다.');
}
});
},
/**
* 폼 유효성 검증
* baseData/bldgNewPrcCrtrAmt/popup.jsp 패턴과 동일하게 적용
* @returns {boolean} 유효성 검증 결과
*/
validate: function() {
if (!$("#rgnSeCd").val()) {
alert('지역구분을 선택하세요.');
$("#rgnSeCd").focus();
return false;
}
if (!$("#dsclMthdCd").val()) {
alert('적발방법을 선택하세요.');
$("#dsclMthdCd").focus();
return false;
}
if (!$("#stdgEmdCd").val()) {
alert('법정동을 선택하세요.');
$("#stdgEmdCd").focus();
return false;
}
if (!$("#relevyYn").val()) {
alert('재부과여부를 선택하세요.');
$("#relevyYn").focus();
return false;
// 기본 validation-check 속성 기반 검증
var isValid = validateFormByAttributes('crdnForm');
if (isValid) {
// 지역구분 검증
if (!$.trim($('#rgnSeCd').val())) {
var rgnSeElement = document.getElementById('rgnSeCd');
errorElementCreate(rgnSeElement, '지역구분을 선택하세요.', false);
$('#rgnSeCd').focus();
return false;
}
// 적발방법 검증
if (!$.trim($('#dsclMthdCd').val())) {
var dsclMthdElement = document.getElementById('dsclMthdCd');
errorElementCreate(dsclMthdElement, '적발방법을 선택하세요.', false);
$('#dsclMthdCd').focus();
return false;
}
// 법정동 검증
if (!$.trim($('#stdgEmdCd').val())) {
var stdgEmdElement = document.getElementById('stdgEmdCd');
errorElementCreate(stdgEmdElement, '법정동을 선택하세요.', false);
$('#stdgEmdCd').focus();
return false;
}
// 재부과여부 검증
if (!$.trim($('#relevyYn').val())) {
var relevyElement = document.getElementById('relevyYn');
errorElementCreate(relevyElement, '재부과여부를 선택하세요.', false);
$('#relevyYn').focus();
return false;
}
// 비고 글자수 검증 (varchar(1000) 제한)
var rmrk = $.trim($('#rmrk').val());
if (rmrk && rmrk.length > 1000) {
var rmrkElement = document.getElementById('rmrk');
errorElementCreate(rmrkElement, '비고는 1000자 이내로 입력하세요. (현재: ' + rmrk.length + '자)', false);
$('#rmrk').focus();
return false;
}
}
return true;
return isValid;
}
};

@ -529,13 +529,31 @@ var buildContextUrl = function(url) {
/**
* 공통코드를 조회하여 select box에 option을 추가하는 함수
* 중요로직: 코드 그룹 ID를 기준으로 해당 코드들을 조회하여 select box를 동적으로 생성
* 확장된 파라미터를 통해 정렬 컬럼, 정렬 방향, 추가 검색 조건 등을 설정할 있음
*
* @param {string} cdGroupId - 코드 그룹 ID (: 'RGN_SE_CD', 'DSCL_MTHD_CD' )
* @param {string} selectId - select 엘리먼트의 ID
* @param {string} firstOptionText - 첫번째 옵션 텍스트 (: '전체', '선택하세요' )
* @param {string} selectedValue - 선택될 (옵션)
* @param {object} options - 추가 옵션 객체 (옵션)
* @param {string} options.sortColumn - 정렬 컬럼 (: 'SORT_ORDR', 'CD_NM', 'CD_ID' )
* @param {boolean} options.sortAscending - 정렬 방향 (true: 오름차순, false: 내림차순)
* @param {string} options.searchCdId - 코드 ID 검색 조건
* @param {string} options.searchCdNm - 코드명 검색 조건
* @param {string} options.searchUseYn - 사용 여부 (기본값: 'Y')
* @param {string} options.searchAttribute1 - 속성1 검색 조건
* @param {string} options.searchAttribute2 - 속성2 검색 조건
* @param {string} options.searchAttribute3 - 속성3 검색 조건
* @param {string} options.searchAttribute4 - 속성4 검색 조건
* @param {string} options.searchAttribute5 - 속성5 검색 조건
* @param {string} options.searchRegDttmStart - 등록일시 시작일
* @param {string} options.searchRegDttmEnd - 등록일시 종료일
* @param {string} options.searchRgtr - 등록자 검색 조건
* @param {string} options.searchMdfcnDttmStart - 수정일시 시작일
* @param {string} options.searchMdfcnDttmEnd - 수정일시 종료일
* @param {string} options.searchMdfr - 수정자 검색 조건
*/
function commonCodeSelectAjax(cdGroupId, selectId, firstOptionText, selectedValue) {
function commonCodeSelectAjax(cdGroupId, selectId, firstOptionText, selectedValue, options) {
if (!cdGroupId || !selectId) {
console.error('commonCodeSelectAjax: cdGroupId와 selectId는 필수 파라미터입니다.');
return;
@ -556,14 +574,42 @@ function commonCodeSelectAjax(cdGroupId, selectId, firstOptionText, selectedValu
$select.find('option:first').text(firstOptionText).val('');
}
// options 객체가 없으면 빈 객체로 초기화
options = options || {};
// AJAX 요청 데이터 구성 - 중요로직: 백엔드 CmmnCodeSearchVO와 정확히 매핑
var requestData = {
searchCdGroupId: cdGroupId, // 필수 파라미터
searchUseYn: options.searchUseYn || 'Y' // 기본값: 사용 중인 코드만 조회
};
// 추가 검색 조건들을 requestData에 추가 (값이 있는 경우만)
if (options.searchCdId) requestData.searchCdId = options.searchCdId;
if (options.searchCdNm) requestData.searchCdNm = options.searchCdNm;
if (options.searchAttribute1) requestData.searchAttribute1 = options.searchAttribute1;
if (options.searchAttribute2) requestData.searchAttribute2 = options.searchAttribute2;
if (options.searchAttribute3) requestData.searchAttribute3 = options.searchAttribute3;
if (options.searchAttribute4) requestData.searchAttribute4 = options.searchAttribute4;
if (options.searchAttribute5) requestData.searchAttribute5 = options.searchAttribute5;
if (options.searchRegDttmStart) requestData.searchRegDttmStart = options.searchRegDttmStart;
if (options.searchRegDttmEnd) requestData.searchRegDttmEnd = options.searchRegDttmEnd;
if (options.searchRgtr) requestData.searchRgtr = options.searchRgtr;
if (options.searchMdfcnDttmStart) requestData.searchMdfcnDttmStart = options.searchMdfcnDttmStart;
if (options.searchMdfcnDttmEnd) requestData.searchMdfcnDttmEnd = options.searchMdfcnDttmEnd;
if (options.searchMdfr) requestData.searchMdfr = options.searchMdfr;
// 정렬 관련 파라미터 추가
if (options.sortColumn) {
requestData.sortColumn = options.sortColumn;
// sortAscending이 명시적으로 false인 경우에만 false로 설정 (기본값: true)
requestData.sortAscending = options.sortAscending !== false;
}
// AJAX로 코드 상세 목록 조회
$.ajax({
url: '/system/code/detail/list.ajax',
type: 'POST',
data: {
cdGroupId: cdGroupId,
useYn: 'Y' // 사용 중인 코드만 조회
},
url: '/common/code/detail/list.ajax',
type: 'GET',
data: requestData,
success: function(response) {
if (response && response.success) {
// 응답 데이터 구조 확인 (그리드용 응답의 경우 response.data.data에 실제 배열이 있을 수 있음)
@ -577,10 +623,13 @@ function commonCodeSelectAjax(cdGroupId, selectId, firstOptionText, selectedValu
return;
}
// 정렬순서(sortOrdr) 기준으로 정렬
codeList.sort(function(a, b) {
return (a.sortOrdr || 0) - (b.sortOrdr || 0);
});
// 정렬 처리 - 중요로직: 백엔드에서 정렬되지 않은 경우 클라이언트에서 기본 정렬 적용
if (!options.sortColumn) {
// 정렬 컬럼이 지정되지 않은 경우 기본적으로 정렬순서(sortOrdr) 기준으로 정렬
codeList.sort(function(a, b) {
return (a.sortOrdr || 0) - (b.sortOrdr || 0);
});
}
// option 추가
$.each(codeList, function(index, item) {

Loading…
Cancel
Save