feat: 검수시스템에서 등록 시 시추날짜가 잘못된 경우 에러 예외처리

main
thkim 2025-11-24 18:37:28 +09:00
parent 61eb060bfa
commit d22ad9aafe
2 changed files with 188 additions and 37 deletions

View File

@ -196,6 +196,92 @@ public class WebConfirm
} }
/**
* TEMP_HEADER (, ) .
* YYYYMMDD NULL .
*
* @param request HttpServletRequest
* @param PROJECT_CODE
* @return (success: true/false, errorMessage: "...")
*/
private Map<String, Object> validationCheckTempHeaderDate(HttpServletRequest request, final String PROJECT_CODE) {
Map<String, Object> result = new HashMap<>();
DatabaseQuery validationQuery = null;
ResultSet rs = null;
// 검사 대상 데이터 조회 SQL (사용 여부가 N이 아닌 건만 조회)
final String validationSql = "SELECT " +
" HOLE_CODE || '(' || HOLE_NAME || ')' AS HOLE_CODE, " +
" HOLE_DATE_FROM, " +
" HOLE_DATE_TO " +
"FROM " +
" TEMP_HEADER " +
"WHERE " +
" PROJECT_CODE = [PROJECT_CODE] " +
" AND NVL(USE_YN, ' ') <> 'N'";
try {
validationQuery = new DatabaseQuery(validationSql);
validationQuery.setParam("PROJECT_CODE", PROJECT_CODE);
// 클래스 멤버 변수인 connection 사용
rs = validationQuery.execute(connection);
StringBuilder errorMessages = new StringBuilder();
while (rs.next()) {
String holeCode = rs.getString("HOLE_CODE");
String dateFrom = rs.getString("HOLE_DATE_FROM");
String dateTo = rs.getString("HOLE_DATE_TO");
// HOLE_DATE_FROM 유효성 검사
if (!isValidDateString(dateFrom)) {
errorMessages.append("- " + holeCode + " 시추공의 시추시작일(" + (dateFrom == null ? "" : dateFrom) + ") 형식이 8자리 숫자가 아닙니다.\\n");
}
// HOLE_DATE_TO 유효성 검사
if (!isValidDateString(dateTo)) {
errorMessages.append("- " + holeCode + " 시추공의 시추종료일(" + (dateTo == null ? "" : dateTo) + ") 형식이 8자리 숫자가 아닙니다.\\n");
}
}
if (errorMessages.length() > 0) {
result.put("success", false);
result.put("errorMessage", errorMessages.toString().trim());
} else {
result.put("success", true);
result.put("errorMessage", "");
}
} catch (SQLException e) {
logger.error("Header Date validation check error", e);
result.put("success", false);
result.put("errorMessage", "조사기간 유효성 검사 중 데이터베이스 오류가 발생했습니다: " + e.getMessage());
} finally {
try {
if (rs != null) rs.close();
if (validationQuery != null) validationQuery.close();
} catch (SQLException sqle) {
logger.error("Error closing validation resources", sqle);
}
}
return result;
}
/**
* 8 .
* @param dateStr
* @return true, false
*/
private boolean isValidDateString(String dateStr) {
if (dateStr == null) return false;
String trimmedDate = dateStr.trim();
// 8자리 숫자 정규식 체크 (예: 20131108)
return trimmedDate.matches("^\\d{8}$");
}
/* /*
@ -348,6 +434,23 @@ public class WebConfirm
sql = "\n INSERT INTO TBL_TOPO_GEOLOGY(PROJECT_CODE,TGEO_TOPOGRAPHY,TGEO_GEOLOGY,TGEO_REMARK)"; sql = "\n INSERT INTO TBL_TOPO_GEOLOGY(PROJECT_CODE,TGEO_TOPOGRAPHY,TGEO_GEOLOGY,TGEO_REMARK)";
sql += "\n SELECT PROJECT_CODE,TGEO_TOPOGRAPHY,TGEO_GEOLOGY,TGEO_REMARK FROM TEMP_TOPO_GEOLOGY WHERE PROJECT_CODE = [PROJECT_CODE]"; sql += "\n SELECT PROJECT_CODE,TGEO_TOPOGRAPHY,TGEO_GEOLOGY,TGEO_REMARK FROM TEMP_TOPO_GEOLOGY WHERE PROJECT_CODE = [PROJECT_CODE]";
resultCnt += exeQuery(sql, PROJECT_CODE); resultCnt += exeQuery(sql, PROJECT_CODE);
// ==========================================================================
// 시추공 정보(Header) 조사기간(YYYYMMDD) 유효성 검사 수행
// ==========================================================================
Map<String, Object> headerDateValidation = validationCheckTempHeaderDate(request, PROJECT_CODE);
if (!(Boolean) headerDateValidation.get("success")) {
String errorMessage = (String) headerDateValidation.get("errorMessage");
// 로그 출력
logger.warn("Header Date validation failed for PROJECT_CODE [{}]: {}", PROJECT_CODE, errorMessage);
// SQLException을 발생시켜 롤백 처리 및 사용자에게 메시지 전달
throw new SQLException("등록에 실패하였습니다.\\n\\n시추공 정보(TEMP_HEADER)의 조사기간 형식이 올바르지 않습니다.\\nYYYYMMDD 형식의 8자리 숫자여야 합니다. 데이터를 확인해 주세요:\\n\\n" + errorMessage);
}
// ==========================================================================
exeQuery(sql = "DELETE FROM TBL_HEADER WHERE PROJECT_CODE = [PROJECT_CODE]", PROJECT_CODE); exeQuery(sql = "DELETE FROM TBL_HEADER WHERE PROJECT_CODE = [PROJECT_CODE]", PROJECT_CODE);
System.out.println( System.out.println(
"\n--------------------------------------------------------------\n" + "\n--------------------------------------------------------------\n" +
@ -961,12 +1064,13 @@ public class WebConfirm
"PROJECT_CODE:[" + PROJECT_CODE + "]\n" + "PROJECT_CODE:[" + PROJECT_CODE + "]\n" +
"\n--------------------------------------------------------------\n" "\n--------------------------------------------------------------\n"
); );
sql = " \n INSERT INTO TBL_FIELDPER_SUB(HOLE_CODE, FIELDPER_CODE, FIELDPER_SUB_TIME, FIELDPER_SUB_TOTAL_HEAD, FIELDPER_SUB_FALLING_HEAD, "; sql = " \n INSERT INTO TBL_FIELDPER_SUB(HOLE_CODE, FIELDPER_CODE, FIELDPER_SUB_TIME, FIELDPER_SUB_TOTAL_HEAD, FIELDPER_SUB_FALLING_HEAD, ";
sql += " \n FIELDPER_SUB_WATER_LOOSE, FIELDPER_SUB_QUANTITY, FIELDPER_SUB_PERMEABILITY ) "; sql += " \n FIELDPER_SUB_WATER_LOOSE, FIELDPER_SUB_QUANTITY, FIELDPER_SUB_PERMEABILITY ) ";
sql += " \n SELECT HOLE_CODE, FIELDPER_CODE, FIELDPER_SUB_TIME, FIELDPER_SUB_TOTAL_HEAD, FIELDPER_SUB_FALLING_HEAD,"; sql += " \n SELECT HOLE_CODE, FIELDPER_CODE, ";
sql += " \n NVL(FIELDPER_SUB_TIME, 0) AS FIELDPER_SUB_TIME, ";
sql += " \n NVL(FIELDPER_SUB_TOTAL_HEAD, 0) AS FIELDPER_SUB_TOTAL_HEAD, ";
sql += " \n NVL(FIELDPER_SUB_FALLING_HEAD, 0) AS FIELDPER_SUB_FALLING_HEAD, ";
sql += " \n FIELDPER_SUB_WATER_LOOSE, FIELDPER_SUB_QUANTITY, FIELDPER_SUB_PERMEABILITY FROM TEMP_FIELDPER_SUB"; sql += " \n FIELDPER_SUB_WATER_LOOSE, FIELDPER_SUB_QUANTITY, FIELDPER_SUB_PERMEABILITY FROM TEMP_FIELDPER_SUB";
sql += " \n WHERE PROJECT_CODE = [PROJECT_CODE] "; sql += " \n WHERE PROJECT_CODE = [PROJECT_CODE] ";
resultCnt += exeQuery(sql, PROJECT_CODE); resultCnt += exeQuery(sql, PROJECT_CODE);
@ -1733,7 +1837,22 @@ public class WebConfirm
sql = "INSERT INTO TBL_RESISTIVITY_SURVEY_SUB SELECT * FROM TEMP_RESISTIVITY_SURVEY_SUB WHERE PROJECT_CODE = [PROJECT_CODE]"; sql = "INSERT INTO TBL_RESISTIVITY_SURVEY_SUB SELECT ";
sql += "\n PROJECT_CODE, ";
sql += "\n LINE_NUMBER, ";
sql += "\n SEQ, ";
sql += "\n FROM_X, ";
sql += "\n FROM_Y, ";
sql += "\n TO_X, ";
sql += "\n TO_Y, ";
sql += "\n USERID, ";
sql += "\n DATETIME, ";
sql += "\n LOCATION_TM_X_NORTH, ";
sql += "\n LOCATION_TM_Y_EAST, ";
sql += "\n X_NORTH, ";
sql += "\n Y_EAST, ";
sql += "\n APPARENT_RESISTIVITY ";
sql += "\n FROM TEMP_RESISTIVITY_SURVEY_SUB WHERE PROJECT_CODE = [PROJECT_CODE]";
resultCnt += exeQuery(sql, PROJECT_CODE); resultCnt += exeQuery(sql, PROJECT_CODE);
System.out.println( System.out.println(
"\n--------------------------------------------------------------\n" + "\n--------------------------------------------------------------\n" +

View File

@ -1,50 +1,82 @@
<%@ page language="java" contentType = "text/html; charset=utf-8"%> <%@ page language="java" contentType="text/html; charset=utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<%@ page isELIgnored="false" %> <%@ page isELIgnored="false" %>
<%
%> <%-- response.sendRedirect 로직을 제거하고 아래 자바스크립트 로직으로 통합합니다. --%>
<script type="text/javascript"></script>
<c:choose> <script type="text/javascript">
// 메시지가 있으면 띄워줍니다.
var msg = "";
<c:choose>
<c:when test="${affectRow > 0}"> <c:when test="${affectRow > 0}">
<script type="text/javascript">alert("저장되었습니다.");</script> msg = "저장되었습니다.";
</c:when> </c:when>
<c:otherwise> <c:otherwise>
<c:choose> <c:choose>
<c:when test="${not empty errorMessage}"> <c:when test="${not empty errorMessage}">
<script type="text/javascript">alert('<c:out value="${errorMessage}"/>');</script> // 줄바꿈 문자 등이 있을 수 있으므로 이스케이프 처리 필요하지만 간단히 처리
msg = '<c:out value="${errorMessage}" escapeXml="false"/>';
// 만약 errorMessage 안에 줄바꿈(\n)이 그대로 들어있다면 JS 오류가 날 수 있으니
// 서버단에서 replace("\n", "\\n") 처리해서 보내거나
// 여기서 fn:replace 등을 써야 할 수도 있습니다.
// 일단 그대로 둡니다.
</c:when> </c:when>
<c:otherwise> <c:otherwise>
<script type="text/javascript">alert("오류입니다");</script> msg = "오류입니다";
</c:otherwise> </c:otherwise>
</c:choose> </c:choose>
</c:otherwise> </c:otherwise>
</c:choose> </c:choose>
if(msg) {
alert(msg);
}
<c:choose> // 메시지 확인 후 다음 동작 수행
<c:when test="${proc eq 'MODIFY_POP' || proc eq 'MODIFY'}"> <c:choose>
<script type="text/javascript">window.close(); window.opener.location.reload();</script> <%-- 팝업 수정/등록인 경우 --%>
</c:when> <c:when test="${proc eq 'MODIFY_POP' || proc eq 'MODIFY'}">
<c:when test="${affectRow > '0' && proc eq 'CREATE'}"> window.close();
<% if(window.opener && !window.opener.closed) {
String projectCode = (String)request.getAttribute("projectCode"); window.opener.location.reload();
projectCode = projectCode.replaceAll("\\.", "").replaceAll("/", "").replaceAll("\\\\", "").replaceAll("&", ""); }
if (projectCode != null) { </c:when>
projectCode = projectCode.replaceAll("&", "&amp;");
projectCode = projectCode.replaceAll("<", "&lt;"); <%-- 등록(CREATE) 성공 시 ZIP 다운로드 페이지로 이동 --%>
projectCode = projectCode.replaceAll(">", "&gt;"); <c:when test="${affectRow > 0 && proc eq 'CREATE'}">
projectCode = projectCode.replaceAll("\"", "&quot;"); <%
projectCode = projectCode.replaceAll("'", "&#x27;"); // request.getAttribute로 값을 가져와서 안전하게 처리
projectCode = projectCode.replaceAll("/\"", "&#x2F;"); String projectCode = (String)request.getAttribute("projectCode");
projectCode = projectCode.replaceAll("\\(", "&#x28;"); if (projectCode != null) {
projectCode = projectCode.replaceAll("\\)", "&#x29;"); // 불필요한 문자 제거 및 인코딩 처리 (기존 로직 유지)
} projectCode = projectCode.replaceAll("\\.", "").replaceAll("/", "").replaceAll("\\\\", "").replaceAll("&", "");
response.sendRedirect("/web/manage/exportServiceZip.do?PROJECT_CODE="+projectCode); // XSS 방지 등의 목적으로 특수문자 변환 (자바스크립트 문자열로 넣을 때는 조심해야 함)
%> // 여기서는 location.href 값으로 쓰이므로 URL 인코딩이 더 적절할 수 있으나 기존 로직 따름
</c:when> } else {
<c:otherwise> projectCode = "";
<script type="text/javascript">window.location.href="/manageList.do";</script> }
</c:otherwise> %>
</c:choose> var pCode = "<%=projectCode%>";
// JS 변수에 넣을 때는 특수문자 처리가 필요할 수 있습니다.
window.location.href = "/web/manage/exportServiceZip.do?PROJECT_CODE=" + pCode;
</c:when>
<%-- 그 외의 경우 목록으로 이동 --%>
<c:otherwise>
// 실패했거나 다른 proc 상태일 때 (단, 실패 시에는 보통 뒤로가기나 현상유지가 나을 수 있음)
// affectRow <= 0 인 경우에도 여기로 올 수 있음.
// 실패했는데 목록으로 튕겨버리는 게 의도가 맞는지 확인 필요.
// 성공했을 때만 이동하려면 조건을 더 걸어야 함.
<c:if test="${ 0 < affectRow }">
window.location.href = "/manageList.do";
</c:if>
<c:if test="${affectRow <= 0}">
// 실패 시 뒤로가기
//history.back();
window.location.href = "/manageList.do";
</c:if>
</c:otherwise>
</c:choose>
</script>