기준자료 > 건물신축가격기준액

1차 완료
dev
박성영 4 months ago
parent a4459cc0fb
commit 3a6d369905

@ -215,4 +215,31 @@ public class StringUtil {
}
return str.substring(0, maxLength - suffixLength) + suffix;
}
/**
* UTF-8 .
* 3, / 1 .
*
* @param str
* @return , null 0
*/
public static int calculateUtf8ByteLength(String str) {
if (str == null || str.isEmpty()) {
return 0;
}
int byteLength = 0;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
// 한글 유니코드 범위 확인
if ((c >= 0xAC00 && c <= 0xD7A3) || (c >= 0x3131 && c <= 0x318E)) {
byteLength += 3; // 한글은 3바이트
} else {
byteLength += 1; // 영문/숫자는 1바이트
}
}
return byteLength;
}
}

@ -87,7 +87,6 @@ public class BldgNewPrcCrtrAmtController {
/**
* .
* PK(+) .
* @param vo VO
* @return ResponseEntity
*/
@ -95,34 +94,12 @@ public class BldgNewPrcCrtrAmtController {
@Operation(summary = "등록", description = "신규 데이터 등록")
public ResponseEntity<?> register(@ModelAttribute BldgNewPrcCrtrAmtVO vo){
log.debug("건물신축가격기준액 등록 요청 - 연도: {}, 번호: {}, 용도: {}", vo.getYr(), vo.getNo(), vo.getBdstUsg());
// PK(연도+번호) 필수값 검증
if (vo.getYr() == null || vo.getYr().trim().isEmpty()) {
log.warn("건물신축가격기준액 등록 실패 - 연도 미입력");
return ApiResponseUtil.error("연도는 필수값입니다.");
}
if (vo.getNo() == null || vo.getNo().trim().isEmpty()) {
log.warn("건물신축가격기준액 등록 실패 - 번호 미입력");
return ApiResponseUtil.error("번호는 필수값입니다.");
}
// PK 중복 체크
int duplicateCount = service.selectDuplicateCheck(vo);
if (duplicateCount > 0) {
log.warn("건물신축가격기준액 등록 실패 - 중복된 PK: 연도={}, 번호={}", vo.getYr(), vo.getNo());
return ApiResponseUtil.error("이미 존재하는 연도와 번호입니다. 다른 값을 입력해주세요.");
}
// 등록자 정보 설정 및 등록 수행
vo.setRgtr(SessionUtil.getUserId());
int r = service.insert(vo);
log.debug("건물신축가격기준액 등록 완료 - 등록 건수: {}", r);
return ApiResponseUtil.success(r);
}
/**
* .
* PK(+) .
* @param vo VO
* @return ResponseEntity
*/
@ -130,26 +107,12 @@ public class BldgNewPrcCrtrAmtController {
@Operation(summary = "수정", description = "기존 데이터 수정")
public ResponseEntity<?> update(@ModelAttribute BldgNewPrcCrtrAmtVO vo){
log.debug("건물신축가격기준액 수정 요청 - 연도: {}, 번호: {}, 용도: {}", vo.getYr(), vo.getNo(), vo.getBdstUsg());
// PK(연도+번호) 필수값 검증
if (vo.getYr() == null || vo.getYr().trim().isEmpty()) {
log.warn("건물신축가격기준액 수정 실패 - 연도 미입력");
return ApiResponseUtil.error("연도는 필수값입니다.");
}
if (vo.getNo() == null || vo.getNo().trim().isEmpty()) {
log.warn("건물신축가격기준액 수정 실패 - 번호 미입력");
return ApiResponseUtil.error("번호는 필수값입니다.");
}
// 수정 수행
int r = service.update(vo);
log.debug("건물신축가격기준액 수정 완료 - 수정 건수: {}", r);
return ApiResponseUtil.success(r);
}
/**
* .
* PK(+) .
* @param vo PK (yr, no) VO
* @return ResponseEntity
*/
@ -157,20 +120,7 @@ public class BldgNewPrcCrtrAmtController {
@Operation(summary = "삭제", description = "기존 데이터 삭제")
public ResponseEntity<?> delete(@ModelAttribute BldgNewPrcCrtrAmtVO vo){
log.debug("건물신축가격기준액 삭제 요청 - 연도: {}, 번호: {}", vo.getYr(), vo.getNo());
// PK(연도+번호) 필수값 검증
if (vo.getYr() == null || vo.getYr().trim().isEmpty()) {
log.warn("건물신축가격기준액 삭제 실패 - 연도 미입력");
return ApiResponseUtil.error("연도는 필수값입니다.");
}
if (vo.getNo() == null || vo.getNo().trim().isEmpty()) {
log.warn("건물신축가격기준액 삭제 실패 - 번호 미입력");
return ApiResponseUtil.error("번호는 필수값입니다.");
}
// 삭제 수행
int r = service.delete(vo);
log.debug("건물신축가격기준액 삭제 완료 - 삭제 건수: {}", r);
return ApiResponseUtil.success(r);
}
}

@ -1,5 +1,8 @@
package go.kr.project.baseData.bldgNewPrcCrtrAmt.service.impl;
import egovframework.exception.MessageException;
import egovframework.util.SessionUtil;
import egovframework.util.StringUtil;
import go.kr.project.baseData.bldgNewPrcCrtrAmt.mapper.BldgNewPrcCrtrAmtMapper;
import go.kr.project.baseData.bldgNewPrcCrtrAmt.model.BldgNewPrcCrtrAmtVO;
import go.kr.project.baseData.bldgNewPrcCrtrAmt.service.BldgNewPrcCrtrAmtService;
@ -65,35 +68,109 @@ public class BldgNewPrcCrtrAmtServiceImpl extends EgovAbstractServiceImpl implem
/**
* .
* PK(+) .
* @param vo VO
* @return
* @throws MessageException PK
*/
@Override
public int insert(BldgNewPrcCrtrAmtVO vo) {
log.debug("건물신축가격기준액 등록 - 연도: {}, 번호: {}, 용도: {}", vo.getYr(), vo.getNo(), vo.getBdstUsg());
return mapper.insert(vo);
// PK(연도+번호) 필수값 검증
if (vo.getYr() == null || vo.getYr().trim().isEmpty()) {
log.warn("건물신축가격기준액 등록 실패 - 연도 미입력");
throw new MessageException("연도는 필수값입니다.");
}
if (vo.getNo() == null || vo.getNo().trim().isEmpty()) {
log.warn("건물신축가격기준액 등록 실패 - 번호 미입력");
throw new MessageException("번호는 필수값입니다.");
}
// PK 중복 체크
int duplicateCount = mapper.selectDuplicateCheck(vo);
if (duplicateCount > 0) {
log.warn("건물신축가격기준액 등록 실패 - 중복된 PK: 연도={}, 번호={}", vo.getYr(), vo.getNo());
throw new MessageException("이미 존재하는 연도와 번호입니다. 다른 값을 입력해주세요.");
}
// 건축물 용도 바이트 길이 검증 (한글 3바이트 기준 최대 60바이트)
if (vo.getBdstUsg() != null && !vo.getBdstUsg().trim().isEmpty()) {
int byteLength = StringUtil.calculateUtf8ByteLength(vo.getBdstUsg());
if (byteLength > 60) {
log.warn("건물신축가격기준액 등록 실패 - 건축물 용도 바이트 길이 초과: {}바이트", byteLength);
throw new MessageException("건축물 용도는 최대 60바이트까지 입력 가능합니다. (현재: " + byteLength + "바이트)");
}
}
// 등록자 정보 설정 및 등록 수행
vo.setRgtr(SessionUtil.getUserId());
int result = mapper.insert(vo);
log.debug("건물신축가격기준액 등록 완료 - 등록 건수: {}", result);
return result;
}
/**
* .
* PK(+) .
* @param vo VO
* @return
* @throws MessageException PK
*/
@Override
public int update(BldgNewPrcCrtrAmtVO vo) {
log.debug("건물신축가격기준액 수정 - 연도: {}, 번호: {}, 용도: {}", vo.getYr(), vo.getNo(), vo.getBdstUsg());
return mapper.update(vo);
// PK(연도+번호) 필수값 검증
if (vo.getYr() == null || vo.getYr().trim().isEmpty()) {
log.warn("건물신축가격기준액 수정 실패 - 연도 미입력");
throw new MessageException("연도는 필수값입니다.");
}
if (vo.getNo() == null || vo.getNo().trim().isEmpty()) {
log.warn("건물신축가격기준액 수정 실패 - 번호 미입력");
throw new MessageException("번호는 필수값입니다.");
}
// 건축물 용도 바이트 길이 검증 (한글 3바이트 기준 최대 60바이트)
if (vo.getBdstUsg() != null && !vo.getBdstUsg().trim().isEmpty()) {
int byteLength = StringUtil.calculateUtf8ByteLength(vo.getBdstUsg());
if (byteLength > 60) {
log.warn("건물신축가격기준액 수정 실패 - 건축물 용도 바이트 길이 초과: {}바이트", byteLength);
throw new MessageException("건축물 용도는 최대 60바이트까지 입력 가능합니다. (현재: " + byteLength + "바이트)");
}
}
// 수정 수행
int result = mapper.update(vo);
log.debug("건물신축가격기준액 수정 완료 - 수정 건수: {}", result);
return result;
}
/**
* .
* PK(+) .
* @param vo PK (yr, no) VO
* @return
* @throws MessageException PK
*/
@Override
public int delete(BldgNewPrcCrtrAmtVO vo) {
log.debug("건물신축가격기준액 삭제 - 연도: {}, 번호: {}", vo.getYr(), vo.getNo());
return mapper.delete(vo);
// PK(연도+번호) 필수값 검증
if (vo.getYr() == null || vo.getYr().trim().isEmpty()) {
log.warn("건물신축가격기준액 삭제 실패 - 연도 미입력");
throw new MessageException("연도는 필수값입니다.");
}
if (vo.getNo() == null || vo.getNo().trim().isEmpty()) {
log.warn("건물신축가격기준액 삭제 실패 - 번호 미입력");
throw new MessageException("번호는 필수값입니다.");
}
// 삭제 수행
int result = mapper.delete(vo);
log.debug("건물신축가격기준액 삭제 완료 - 삭제 건수: {}", result);
return result;
}
/**
@ -106,4 +183,5 @@ public class BldgNewPrcCrtrAmtServiceImpl extends EgovAbstractServiceImpl implem
log.debug("건물신축가격기준액 중복 체크 - 연도: {}, 번호: {}", vo.getYr(), vo.getNo());
return mapper.selectDuplicateCheck(vo);
}
}

@ -220,6 +220,20 @@
var responseObj = JSON.parse(ev.xhr.response);
});
// 행 더블클릭 이벤트 - 건물신축가격기준액 상세 조회 팝업으로 이동
this.instance.on('dblclick', function(ev) {
if (ev.rowKey !== undefined && ev.columnName !== '_number') {
var rowData = self.instance.getRow(ev.rowKey);
if (rowData && rowData.yr && rowData.no) {
var url = '<c:url value="/baseData/bldgNewPrcCrtrAmt/popup.do"/>?yr=' +
encodeURIComponent(rowData.yr) + '&no=' +
encodeURIComponent(rowData.no) + '&mode=V';
window.open(url, 'bldgNewPrcCrtrAmtView', 'width=700,height=350,scrollbars=yes');
}
}
});
}
},
@ -232,7 +246,7 @@
// 검색 버튼 클릭 이벤트
$('#search_btn').on('click', function() {
// 페이지를 1로 리셋
self.grid.instance.readData(1);
self.grid.instance.readData();
});
// 검색어 입력 필드에서 엔터키 이벤트 처리
@ -243,27 +257,11 @@
}
});
// perPage 변경 이벤트 추가
$('#perPageSelect').on('change', function() {
var perPage = parseInt($(this).val(), 10);
// Grid의 perPage 설정 변경 및 데이터 리로드
self.grid.instance.setPerPage(perPage);
});
// 등록 버튼 클릭 이벤트
$('#registerBtn').on('click', function() {
self.openRegisterPopup();
});
// 수정 버튼 클릭 이벤트
$('#btnEdit').on('click', function() {
self.openEditPopup();
});
// 삭제 버튼 클릭 이벤트
$('#btnDelete').on('click', function() {
self.openDeletePopup();
});
},
/**
@ -273,43 +271,12 @@
window.open('<c:url value="/baseData/bldgNewPrcCrtrAmt/popup.do"/>', 'bldgNewPrcCrtrAmtReg', 'width=700,height=500,scrollbars=yes');
},
/**
* 수정 팝업 열기
*/
openEditPopup: function() {
if (!this.selectedRow) {
alert('수정할 행을 선택하세요.');
return;
}
var url = '<c:url value="/baseData/bldgNewPrcCrtrAmt/popup.do"/>?yr=' +
encodeURIComponent(this.selectedRow.yr) + '&no=' +
encodeURIComponent(this.selectedRow.no);
window.open(url, 'bldgNewPrcCrtrAmtEdit', 'width=700,height=500,scrollbars=yes');
},
/**
* 삭제 팝업 열기
*/
openDeletePopup: function() {
if (!this.selectedRow) {
alert('삭제할 행을 선택하세요.');
return;
}
var url = '<c:url value="/baseData/bldgNewPrcCrtrAmt/popup.do"/>?yr=' +
encodeURIComponent(this.selectedRow.yr) + '&no=' +
encodeURIComponent(this.selectedRow.no) + '&mode=D';
window.open(url, 'bldgNewPrcCrtrAmtDel', 'width=700,height=500,scrollbars=yes');
},
/**
* 목록 새로고침
*/
refreshList: function() {
if (this.grid.instance) {
var currentPage = this.grid.instance.getPagination().getCurrentPage() || 1;
this.grid.instance.readData(currentPage);
this.grid.instance.readData();
}
},

@ -1,5 +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">
@ -15,43 +18,77 @@
<tr>
<th class="th"><span class="required">*</span> 연도</th>
<td>
<input type="text" id="yr" name="yr" class="input calender"
value="${data.yr}" maxlength="4"
validation-check="required"
style="width: 100px;"
placeholder="YYYY" readonly />
<div class="hint-message">※ 4자리 연도를 선택하세요. (클릭하여 연도 선택)</div>
<c:choose>
<c:when test="${param.mode eq 'V'}">
<span class="view-text">${data.yr}</span>
<input type="hidden" id="yr" name="yr" value="${data.yr}" />
</c:when>
<c:otherwise>
<input type="text" id="yr" name="yr" class="input calender"
value="${data.yr}" maxlength="4"
validation-check="required"
style="width: 100px;"
placeholder="YYYY" readonly />
<div class="hint-message">※ 4자리 연도를 선택하세요. (클릭하여 연도 선택)</div>
</c:otherwise>
</c:choose>
</td>
</tr>
<tr>
<th class="th"><span class="required">*</span> 번호</th>
<td>
<input type="text" id="no" name="no" class="input"
value="${data.no}" maxlength="1"
validation-check="required"
style="width: 80px;"
placeholder="1" />
<div class="hint-message">※ 1~9 사이의 한 자리 번호를 입력하세요.</div>
<c:choose>
<c:when test="${param.mode eq 'V'}">
<span class="view-text">${data.no}</span>
<input type="hidden" id="no" name="no" value="${data.no}" />
</c:when>
<c:otherwise>
<input type="text" id="no" name="no" class="input"
value="${data.no}" maxlength="1"
validation-check="required"
style="width: 80px;"
placeholder="1" />
<div class="hint-message">※ 1~9 사이의 한 자리 번호를 입력하세요.</div>
</c:otherwise>
</c:choose>
</td>
</tr>
<tr>
<th class="th"><span class="required">*</span> 건축물 용도</th>
<td>
<input type="text" id="bdstUsg" name="bdstUsg" class="input"
value="${data.bdstUsg}" maxlength="60"
validation-check="required"
style="width: 400px;"
placeholder="건축물 용도를 입력하세요" />
<c:choose>
<c:when test="${param.mode eq 'V'}">
<span class="view-text">${data.bdstUsg}</span>
<input type="hidden" id="bdstUsg" name="bdstUsg" value="${data.bdstUsg}" />
</c:when>
<c:otherwise>
<input type="text" id="bdstUsg" name="bdstUsg" class="input"
value="${data.bdstUsg}" maxlength="60"
validation-check="required"
style="width: 400px;"
placeholder="건축물 용도를 입력하세요" />
</c:otherwise>
</c:choose>
</td>
</tr>
<tr>
<th class="th"><span class="required">*</span> 기준액(원/㎡)</th>
<td>
<input type="text" id="bldgNewPrcCrtrAmt" name="bldgNewPrcCrtrAmt" class="input"
value="${data.bldgNewPrcCrtrAmt}"
validation-check="required"
style="width: 200px; text-align: right;" />
<div class="hint-message">※ 숫자만 입력하세요. (천단위 콤마는 자동으로 처리됩니다.)</div>
<c:choose>
<c:when test="${param.mode eq 'V'}">
<span class="view-text" style="text-align: right;">
<fmt:formatNumber value="${data.bldgNewPrcCrtrAmt}" pattern="#,##0" />
</span>
<input type="hidden" id="bldgNewPrcCrtrAmt" name="bldgNewPrcCrtrAmt" value="${data.bldgNewPrcCrtrAmt}" />
</c:when>
<c:otherwise>
<input type="text" id="bldgNewPrcCrtrAmt" name="bldgNewPrcCrtrAmt" class="input"
value="${data.bldgNewPrcCrtrAmt}"
validation-check="required"
style="width: 200px; text-align: right;" />
<div class="hint-message">※ 숫자만 입력하세요. (천단위 콤마는 자동으로 처리됩니다.)</div>
</c:otherwise>
</c:choose>
</td>
</tr>
</table>
@ -60,9 +97,9 @@
</div>
<div class="popup_foot">
<c:choose>
<c:when test="${param.mode eq 'D'}">
<!-- 삭제 모드 -->
<a href="#" id="btnDelete" class="newbtns bg3">삭제</a>
<c:when test="${param.mode eq 'V'}">
<!-- 삭제/보기 모드: 삭제 버튼만 노출 -->
<a href="#" id="btnDelete" class="newbtns bg2">삭제</a>
</c:when>
<c:when test="${not empty data.yr and not empty data.no}">
<!-- 수정 모드 -->
@ -73,7 +110,7 @@
<a href="#" id="btnSave" class="newbtns bg4">저장</a>
</c:otherwise>
</c:choose>
<a href="#" class="newbtns bg1 modalclose">취소</a>
<a href="#" class="newbtns bg1 modalclose">닫기</a>
</div>
</div>
</div>
@ -93,7 +130,7 @@
var BldgNewPrcCrtrAmtForm = {
/**
* 현재 모드 ('', 'D')
* 현재 모드 ('', 'V')
*/
mode: '${param.mode}',
@ -206,24 +243,20 @@
}
var formData = this.getFormData();
var isEdit = (this.mode !== 'D' && formData.yr && formData.no && '${data.yr}' && '${data.no}');
var url = isEdit ?
'<c:url value="/baseData/bldgNewPrcCrtrAmt/update.ajax"/>' :
'<c:url value="/baseData/bldgNewPrcCrtrAmt/register.ajax"/>';
var url = '<c:url value="/baseData/bldgNewPrcCrtrAmt/register.ajax"/>';
$.ajax({
url: url,
type: 'POST',
data: formData,
success: function(response) {
if (response.success) {
alert(isEdit ? '수정되었습니다.' : '저장되었습니다.');
alert('저장되었습니다.');
if (window.opener && window.opener.refreshList) {
window.opener.refreshList();
}
window.close();
} else {
alert(response.message || (isEdit ? '수정에 실패했습니다.' : '저장에 실패했습니다.'));
alert(response.message || '저장에 실패했습니다.');
}
},
error: function(xhr, status, error) {
@ -272,9 +305,7 @@
* 닫기 처리
*/
cancel: function() {
if (confirm('입력한 내용이 저장되지 않습니다. 창을 닫으시겠습니까?')) {
window.close();
}
window.close();
},
/**
@ -347,7 +378,7 @@
$('#bldgNewPrcCrtrAmtForm').on('keypress', function(e) {
if (e.which === 13) { // 엔터키
e.preventDefault();
if (self.mode === 'D') {
if (self.mode === 'V') {
self.delete();
} else {
self.save();
@ -356,31 +387,12 @@
});
},
/**
* 삭제 모드 처리
*/
initDeleteMode: function() {
if (this.mode === 'D') {
// 입력 필드 비활성화
$('#bldgNewPrcCrtrAmtForm input[type="text"]').prop('disabled', true);
$('#bldgNewPrcCrtrAmtForm input[type="text"]').addClass('disabled');
}
},
/**
* 모듈 초기화
*/
init: function() {
// 삭제 모드 처리
this.initDeleteMode();
// 이벤트 핸들러 설정
this.eventBindEvents();
// 첫 번째 입력 필드에 포커스 (연도 필드는 자동 포커스 제외하여 datepicker 자동 오픈 방지)
if (this.mode !== 'D') {
//$('#no').focus();
}
}
};

Loading…
Cancel
Save